This commit is contained in:
Kyle Spearrin 2016-05-02 17:50:16 -04:00
parent bc3d9c4465
commit e05ed4c1f2
33 changed files with 298 additions and 77 deletions

View file

@ -94,6 +94,14 @@
<HintPath>..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\OkHttp.dll</HintPath> <HintPath>..\..\packages\modernhttpclient.2.4.2\lib\MonoAndroid\OkHttp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Plugin.Settings, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\MonoAndroid10\Plugin.Settings.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Plugin.Settings.Abstractions, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\MonoAndroid10\Plugin.Settings.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath> <HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View file

@ -12,6 +12,7 @@ using Bit.App.Services;
using XLabs.Ioc.Unity; using XLabs.Ioc.Unity;
using XLabs.Ioc; using XLabs.Ioc;
using Bit.Android.Services; using Bit.Android.Services;
using Plugin.Settings;
namespace Bit.Android namespace Bit.Android
{ {
@ -40,6 +41,7 @@ namespace Bit.Android
.RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager()) .RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager())
.RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager()) .RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager())
.RegisterType<ISecureStorageService, KeyStoreStorageService>(new ContainerControlledLifetimeManager()) .RegisterType<ISecureStorageService, KeyStoreStorageService>(new ContainerControlledLifetimeManager())
.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager())
.RegisterType<IApiService, ApiService>(new ContainerControlledLifetimeManager()) .RegisterType<IApiService, ApiService>(new ContainerControlledLifetimeManager())
.RegisterType<ICryptoService, CryptoService>(new ContainerControlledLifetimeManager()) .RegisterType<ICryptoService, CryptoService>(new ContainerControlledLifetimeManager())
.RegisterType<IAuthService, AuthService>(new ContainerControlledLifetimeManager()) .RegisterType<IAuthService, AuthService>(new ContainerControlledLifetimeManager())

View file

@ -5,6 +5,7 @@
<package id="sqlite-net-pcl" version="1.1.1" targetFramework="monoandroid60" /> <package id="sqlite-net-pcl" version="1.1.1" targetFramework="monoandroid60" />
<package id="SQLitePCL.raw" version="0.8.6" targetFramework="monoandroid60" /> <package id="SQLitePCL.raw" version="0.8.6" targetFramework="monoandroid60" />
<package id="Unity" version="3.5.1405-prerelease" targetFramework="monoandroid60" /> <package id="Unity" version="3.5.1405-prerelease" targetFramework="monoandroid60" />
<package id="Xam.Plugins.Settings" version="2.1.0" targetFramework="monoandroid60" />
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid60" /> <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid60" />
<package id="Xamarin.Android.Support.Design" version="23.3.0" targetFramework="monoandroid60" /> <package id="Xamarin.Android.Support.Design" version="23.3.0" targetFramework="monoandroid60" />
<package id="Xamarin.Android.Support.v4" version="23.3.0" targetFramework="monoandroid60" /> <package id="Xamarin.Android.Support.v4" version="23.3.0" targetFramework="monoandroid60" />

View file

@ -7,7 +7,9 @@ namespace Bit.App.Abstractions
{ {
bool IsAuthenticated { get; } bool IsAuthenticated { get; }
string Token { get; set; } string Token { get; set; }
string UserId { get; set; }
void LogOut();
Task<ApiResult<TokenResponse>> TokenPostAsync(TokenRequest request); Task<ApiResult<TokenResponse>> TokenPostAsync(TokenRequest request);
} }
} }

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Views; using Bit.App.Pages;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App namespace Bit.App
@ -11,26 +11,20 @@ namespace Bit.App
public class App : Application public class App : Application
{ {
private readonly IDatabaseService _databaseService; private readonly IDatabaseService _databaseService;
private readonly IAuthService _authService;
public App(IAuthService authService, IDatabaseService databaseService) public App(IAuthService authService, IDatabaseService databaseService)
{ {
_databaseService = databaseService; _databaseService = databaseService;
_authService = authService;
if(authService.IsAuthenticated) if(authService.IsAuthenticated)
{ {
var nav = new NavigationPage(new VaultListPage()); MainPage = new MainPage();
nav.BarBackgroundColor = Color.FromHex("3c8dbc");
nav.BarTextColor = Color.FromHex("ffffff");
MainPage = nav;
} }
else else
{ {
var nav = new NavigationPage(new LoginPage()); MainPage = new LoginNavigationPage();
nav.BarBackgroundColor = Color.FromHex("3c8dbc");
nav.BarTextColor = Color.FromHex("ffffff");
MainPage = nav;
} }
MainPage.BackgroundColor = Color.FromHex("ecf0f5"); MainPage.BackgroundColor = Color.FromHex("ecf0f5");

View file

@ -59,6 +59,10 @@
<Compile Include="Models\Data\SiteData.cs" /> <Compile Include="Models\Data\SiteData.cs" />
<Compile Include="Models\Folder.cs" /> <Compile Include="Models\Folder.cs" />
<Compile Include="Models\Site.cs" /> <Compile Include="Models\Site.cs" />
<Compile Include="Pages\LoginNavigationPage.cs" />
<Compile Include="Pages\MainPage.cs" />
<Compile Include="Pages\SyncPage.cs" />
<Compile Include="Pages\SettingsPage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\DatabaseService.cs" /> <Compile Include="Services\DatabaseService.cs" />
<Compile Include="Services\FolderService.cs" /> <Compile Include="Services\FolderService.cs" />
@ -105,6 +109,14 @@
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Plugin.Settings, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.Settings.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Plugin.Settings.Abstractions, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.Settings.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath> <HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View file

@ -5,6 +5,5 @@ namespace Bit.App.Models.Api
public class ApiError public class ApiError
{ {
public string Message { get; set; } public string Message { get; set; }
public HttpStatusCode StatusCode { get; set; }
} }
} }

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
namespace Bit.App.Models.Api namespace Bit.App.Models.Api
{ {
@ -9,19 +10,26 @@ namespace Bit.App.Models.Api
public bool Succeeded { get; private set; } public bool Succeeded { get; private set; }
public T Result { get; set; } public T Result { get; set; }
public IEnumerable<ApiError> Errors => m_errors; public IEnumerable<ApiError> Errors => m_errors;
public HttpStatusCode StatusCode { get; private set; }
public static ApiResult<T> Success(T result) public static ApiResult<T> Success(T result, HttpStatusCode statusCode)
{ {
return new ApiResult<T> return new ApiResult<T>
{ {
Succeeded = true, Succeeded = true,
Result = result Result = result,
StatusCode = statusCode
}; };
} }
public static ApiResult<T> Failed(params ApiError[] errors) public static ApiResult<T> Failed(HttpStatusCode statusCode, params ApiError[] errors)
{ {
var result = new ApiResult<T> { Succeeded = false }; var result = new ApiResult<T>
{
Succeeded = false,
StatusCode = statusCode
};
if(errors != null) if(errors != null)
{ {
result.m_errors.AddRange(errors); result.m_errors.AddRange(errors);

View file

@ -10,10 +10,11 @@ namespace Bit.App.Models.Data
public FolderData() public FolderData()
{ } { }
public FolderData(Folder folder) public FolderData(Folder folder, string userId)
{ {
Id = folder.Id; Id = folder.Id;
ServerId = folder.ServerId; ServerId = folder.ServerId;
UserId = userId;
Name = folder.Name?.EncryptedString; Name = folder.Name?.EncryptedString;
} }
@ -21,6 +22,7 @@ namespace Bit.App.Models.Data
[AutoIncrement] [AutoIncrement]
public int Id { get; set; } public int Id { get; set; }
public string ServerId { get; set; } public string ServerId { get; set; }
public string UserId { get; set; }
public string Name { get; set; } public string Name { get; set; }
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow; public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;

View file

@ -10,12 +10,13 @@ namespace Bit.App.Models.Data
public SiteData() public SiteData()
{ } { }
public SiteData(Site site) public SiteData(Site site, string userId)
{ {
Id = site.Id; Id = site.Id;
ServerId = site.ServerId; ServerId = site.ServerId;
FolderId = site.FolderId; FolderId = site.FolderId;
ServerFolderId = site.ServerFolderId; ServerFolderId = site.ServerFolderId;
UserId = userId;
Name = site.Name?.EncryptedString; Name = site.Name?.EncryptedString;
Uri = site.Uri?.EncryptedString; Uri = site.Uri?.EncryptedString;
Username = site.Username?.EncryptedString; Username = site.Username?.EncryptedString;
@ -29,6 +30,7 @@ namespace Bit.App.Models.Data
public string ServerId { get; set; } public string ServerId { get; set; }
public int? FolderId { get; set; } public int? FolderId { get; set; }
public string ServerFolderId { get; set; } public string ServerFolderId { get; set; }
public string UserId { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Uri { get; set; } public string Uri { get; set; }
public string Username { get; set; } public string Username { get; set; }

View file

@ -21,9 +21,9 @@ namespace Bit.App.Models
Name = response.Name != null ? new CipherString(response.Name) : null; Name = response.Name != null ? new CipherString(response.Name) : null;
} }
public FolderData ToFolderData() public FolderData ToFolderData(string userId)
{ {
return new FolderData(this); return new FolderData(this, userId);
} }
} }
} }

View file

@ -39,9 +39,9 @@ namespace Bit.App.Models
public CipherString Password { get; set; } public CipherString Password { get; set; }
public CipherString Notes { get; set; } public CipherString Notes { get; set; }
public SiteData ToSiteData() public SiteData ToSiteData(string userId)
{ {
return new SiteData(this); return new SiteData(this, userId);
} }
} }
} }

View file

@ -0,0 +1,15 @@
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class LoginNavigationPage : NavigationPage
{
public LoginNavigationPage()
: base(new LoginPage())
{
BarBackgroundColor = Color.FromHex("3c8dbc");
BarTextColor = Color.FromHex("ffffff");
Title = "Login";
}
}
}

View file

@ -9,7 +9,7 @@ using Bit.App.Models.Api;
using Xamarin.Forms; using Xamarin.Forms;
using XLabs.Ioc; using XLabs.Ioc;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class LoginPage : ContentPage public class LoginPage : ContentPage
{ {
@ -63,12 +63,15 @@ namespace Bit.App.Views
var response = await authService.TokenPostAsync(request); var response = await authService.TokenPostAsync(request);
if(!response.Succeeded) if(!response.Succeeded)
{ {
throw new Exception(); await DisplayAlert("An error occurred", response.Errors.First().Message, "Ok");
return;
} }
cryptoService.Key = key; cryptoService.Key = key;
authService.Token = response.Result.Token; authService.Token = response.Result.Token;
await Navigation.PushAsync(new VaultListPage()); authService.UserId = response.Result.Profile.Id;
Application.Current.MainPage = new MainPage();
}) })
}; };

26
src/App/Pages/MainPage.cs Normal file
View file

@ -0,0 +1,26 @@
using System;
using Bit.App.Abstractions;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class MainPage : TabbedPage
{
public MainPage()
{
var vaultNavigation = new NavigationPage(new VaultListPage());
vaultNavigation.BarBackgroundColor = Color.FromHex("3c8dbc");
vaultNavigation.BarTextColor = Color.FromHex("ffffff");
vaultNavigation.Title = "My Vault";
var settingsNavigation = new NavigationPage(new SettingsPage());
settingsNavigation.BarBackgroundColor = Color.FromHex("3c8dbc");
settingsNavigation.BarTextColor = Color.FromHex("ffffff");
settingsNavigation.Title = "Settings";
Children.Add(vaultNavigation);
Children.Add(new SyncPage());
Children.Add(settingsNavigation);
}
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using Bit.App.Abstractions;
using Xamarin.Forms;
using XLabs.Ioc;
namespace Bit.App.Pages
{
public class SettingsPage : ContentPage
{
private ListView _listView = new ListView();
public SettingsPage()
{
var authService = Resolver.Resolve<IAuthService>();
var logoutButton = new Button
{
Text = "Log Out",
Command = new Command(() =>
{
authService.LogOut();
Application.Current.MainPage = new LoginNavigationPage();
})
};
var stackLayout = new StackLayout { };
stackLayout.Children.Add(logoutButton);
Title = "Settings";
Content = stackLayout;
}
}
}

14
src/App/Pages/SyncPage.cs Normal file
View file

@ -0,0 +1,14 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class SyncPage : ContentPage
{
public SyncPage()
{
Title = "Sync";
Content = null;
}
}
}

View file

@ -8,7 +8,7 @@ using Bit.App.Models;
using Xamarin.Forms; using Xamarin.Forms;
using XLabs.Ioc; using XLabs.Ioc;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultAddFolderPage : ContentPage public class VaultAddFolderPage : ContentPage
{ {

View file

@ -8,7 +8,7 @@ using Bit.App.Models;
using Xamarin.Forms; using Xamarin.Forms;
using XLabs.Ioc; using XLabs.Ioc;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultAddSitePage : ContentPage public class VaultAddSitePage : ContentPage
{ {

View file

@ -6,7 +6,7 @@ using System.Text;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultEditFolderPage : ContentPage public class VaultEditFolderPage : ContentPage
{ {

View file

@ -6,7 +6,7 @@ using System.Text;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultEditSitePage : ContentPage public class VaultEditSitePage : ContentPage
{ {

View file

@ -7,13 +7,13 @@ using Bit.App.Models.View;
using Xamarin.Forms; using Xamarin.Forms;
using XLabs.Ioc; using XLabs.Ioc;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultListPage : ContentPage public class VaultListPage : ContentPage
{ {
private readonly IFolderService _folderService; private readonly IFolderService _folderService;
private readonly ISiteService _siteService; private readonly ISiteService _siteService;
private ListView _listView; private ListView _listView = new ListView();
public VaultListPage() public VaultListPage()
{ {
@ -28,12 +28,8 @@ namespace Bit.App.Views
ToolbarItems.Add(addSiteToolBarItem); ToolbarItems.Add(addSiteToolBarItem);
_listView = new ListView _listView.IsGroupingEnabled = true;
{ _listView.GroupDisplayBinding = new Binding("Name");
IsGroupingEnabled = true,
GroupDisplayBinding = new Binding("Name")
};
_listView.ItemSelected += FolderSelected; _listView.ItemSelected += FolderSelected;
_listView.ItemTemplate = new DataTemplate(() => _listView.ItemTemplate = new DataTemplate(() =>
{ {
@ -45,7 +41,6 @@ namespace Bit.App.Views
Title = "My Vault"; Title = "My Vault";
Content = _listView; Content = _listView;
NavigationPage.SetHasBackButton(this, false);
} }
protected override void OnAppearing() protected override void OnAppearing()

View file

@ -6,7 +6,7 @@ using System.Text;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Views namespace Bit.App.Pages
{ {
public class VaultViewSitePage : ContentPage public class VaultViewSitePage : ContentPage
{ {

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Abstractions; using Bit.App.Abstractions;
@ -20,21 +21,26 @@ namespace Bit.App.Services
public async Task<ApiResult<T>> HandleErrorAsync<T>(HttpResponseMessage response) public async Task<ApiResult<T>> HandleErrorAsync<T>(HttpResponseMessage response)
{ {
var error = new ApiError
{
Message = "An unknown error has occured.",
StatusCode = response.StatusCode
};
try try
{ {
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();
var errorResponseModel = JsonConvert.DeserializeObject<ErrorResponse>(responseContent); var errorResponseModel = JsonConvert.DeserializeObject<ErrorResponse>(responseContent);
error.Message = errorResponseModel.Message;
}
catch(JsonReaderException) { }
return ApiResult<T>.Failed(error); var errors = new List<ApiError>();
foreach(var valError in errorResponseModel.ValidationErrors)
{
foreach(var errorMessage in valError.Value)
{
errors.Add(new ApiError { Message = errorMessage });
}
}
return ApiResult<T>.Failed(response.StatusCode, errors.ToArray());
}
catch(JsonReaderException)
{ }
return ApiResult<T>.Failed(response.StatusCode, new ApiError { Message = "An unknown error has occured." });
} }
} }
} }

View file

@ -5,23 +5,31 @@ using System.Threading.Tasks;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Models.Api; using Bit.App.Models.Api;
using Newtonsoft.Json; using Newtonsoft.Json;
using Plugin.Settings.Abstractions;
namespace Bit.App.Services namespace Bit.App.Services
{ {
public class AuthService : IAuthService public class AuthService : IAuthService
{ {
private const string TokenKey = "token"; private const string TokenKey = "token";
private const string UserIdKey = "userId";
private readonly ISecureStorageService _secureStorage; private readonly ISecureStorageService _secureStorage;
private readonly ISettings _settings;
private readonly ICryptoService _cryptoService; private readonly ICryptoService _cryptoService;
private readonly IApiService _apiService; private readonly IApiService _apiService;
private string _token;
private string _userId;
public AuthService( public AuthService(
ISecureStorageService secureStorage, ISecureStorageService secureStorage,
ISettings settings,
ICryptoService cryptoService, ICryptoService cryptoService,
IApiService apiService) IApiService apiService)
{ {
_secureStorage = secureStorage; _secureStorage = secureStorage;
_settings = settings;
_cryptoService = cryptoService; _cryptoService = cryptoService;
_apiService = apiService; _apiService = apiService;
} }
@ -30,8 +38,19 @@ namespace Bit.App.Services
{ {
get get
{ {
if(_token != null)
{
return _token;
}
var tokenBytes = _secureStorage.Retrieve(TokenKey); var tokenBytes = _secureStorage.Retrieve(TokenKey);
return Encoding.UTF8.GetString(tokenBytes, 0, tokenBytes.Length); if(tokenBytes == null)
{
return null;
}
_token = Encoding.UTF8.GetString(tokenBytes, 0, tokenBytes.Length);
return _token;
} }
set set
{ {
@ -43,6 +62,33 @@ namespace Bit.App.Services
else else
{ {
_secureStorage.Delete(TokenKey); _secureStorage.Delete(TokenKey);
_token = null;
}
}
}
public string UserId
{
get
{
if(_userId != null)
{
return _userId;
}
_userId = _settings.GetValueOrDefault<string>(UserIdKey);
return _userId;
}
set
{
if(value != null)
{
_settings.AddOrUpdateValue(UserIdKey, value);
}
else
{
_settings.Remove(UserIdKey);
_userId = null;
} }
} }
} }
@ -51,10 +97,17 @@ namespace Bit.App.Services
{ {
get get
{ {
return _cryptoService.Key != null && Token != null; return _cryptoService.Key != null && Token != null && UserId != null;
} }
} }
public void LogOut()
{
Token = null;
UserId = null;
_cryptoService.Key = null;
}
public async Task<ApiResult<TokenResponse>> TokenPostAsync(TokenRequest request) public async Task<ApiResult<TokenResponse>> TokenPostAsync(TokenRequest request)
{ {
var requestContent = JsonConvert.SerializeObject(request); var requestContent = JsonConvert.SerializeObject(request);
@ -66,7 +119,7 @@ namespace Bit.App.Services
var responseContent = await response.Content.ReadAsStringAsync(); var responseContent = await response.Content.ReadAsStringAsync();
var responseObj = JsonConvert.DeserializeObject<TokenResponse>(responseContent); var responseObj = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
return ApiResult<TokenResponse>.Success(responseObj); return ApiResult<TokenResponse>.Success(responseObj, response.StatusCode);
} }
} }
} }

View file

@ -51,11 +51,30 @@ namespace Bit.App.Services
} }
set set
{ {
_secureStorage.Store(KeyKey, value); if(value != null)
_keyParameter = new KeyParameter(value); {
_secureStorage.Store(KeyKey, value);
}
else
{
_secureStorage.Delete(KeyKey);
_keyParameter = null;
}
}
}
public string Base64Key
{
get
{
if(Key == null)
{
return null;
}
return Convert.ToBase64String(Key);
} }
} }
public string Base64Key { get { return Convert.ToBase64String(Key); } }
public CipherString Encrypt(string plaintextValue) public CipherString Encrypt(string plaintextValue)
{ {

View file

@ -10,18 +10,25 @@ namespace Bit.App.Services
{ {
public class FolderService : Repository<FolderData, int>, IFolderService public class FolderService : Repository<FolderData, int>, IFolderService
{ {
public FolderService(ISqlService sqlite) private readonly IAuthService _authService;
: base(sqlite) { }
public new async Task<IEnumerable<Folder>> GetAllAsync() public FolderService(
ISqlService sqlService,
IAuthService authService)
: base(sqlService)
{ {
var data = await base.GetAllAsync(); _authService = authService;
return data.Select(f => new Folder(f)); }
public new Task<IEnumerable<Folder>> GetAllAsync()
{
var data = Connection.Table<FolderData>().Where(f => f.UserId == _authService.UserId).Cast<FolderData>();
return Task.FromResult(data.Select(f => new Folder(f)));
} }
public async Task SaveAsync(Folder folder) public async Task SaveAsync(Folder folder)
{ {
var data = new FolderData(folder); var data = new FolderData(folder, _authService.UserId);
data.RevisionDateTime = DateTime.UtcNow; data.RevisionDateTime = DateTime.UtcNow;
if(folder.Id == 0) if(folder.Id == 0)

View file

@ -11,38 +11,38 @@ namespace Bit.App.Services
where TId : IEquatable<TId> where TId : IEquatable<TId>
where T : class, IDataObject<TId>, new() where T : class, IDataObject<TId>, new()
{ {
protected readonly SQLiteConnection _connection; public Repository(ISqlService sqlService)
public Repository(ISqlService sqlite)
{ {
_connection = sqlite.GetConnection(); Connection = sqlService.GetConnection();
} }
protected SQLiteConnection Connection { get; private set; }
protected virtual Task<T> GetByIdAsync(TId id) protected virtual Task<T> GetByIdAsync(TId id)
{ {
return Task.FromResult(_connection.Get<T>(id)); return Task.FromResult(Connection.Get<T>(id));
} }
protected virtual Task<IEnumerable<T>> GetAllAsync() protected virtual Task<IEnumerable<T>> GetAllAsync()
{ {
return Task.FromResult(_connection.Table<T>().Cast<T>()); return Task.FromResult(Connection.Table<T>().Cast<T>());
} }
protected virtual Task CreateAsync(T obj) protected virtual Task CreateAsync(T obj)
{ {
_connection.Insert(obj); Connection.Insert(obj);
return Task.FromResult(0); return Task.FromResult(0);
} }
protected virtual Task ReplaceAsync(T obj) protected virtual Task ReplaceAsync(T obj)
{ {
_connection.Update(obj); Connection.Update(obj);
return Task.FromResult(0); return Task.FromResult(0);
} }
protected virtual Task DeleteAsync(T obj) protected virtual Task DeleteAsync(T obj)
{ {
_connection.Delete<T>(obj.Id); Connection.Delete<T>(obj.Id);
return Task.FromResult(0); return Task.FromResult(0);
} }
} }

View file

@ -10,18 +10,25 @@ namespace Bit.App.Services
{ {
public class SiteService : Repository<SiteData, int>, ISiteService public class SiteService : Repository<SiteData, int>, ISiteService
{ {
public SiteService(ISqlService sqlite) private readonly IAuthService _authService;
: base(sqlite) { }
public new async Task<IEnumerable<Site>> GetAllAsync() public SiteService(
ISqlService sqlService,
IAuthService authService)
: base(sqlService)
{ {
var data = await base.GetAllAsync(); _authService = authService;
return data.Select(s => new Site(s)); }
public new Task<IEnumerable<Site>> GetAllAsync()
{
var data = Connection.Table<SiteData>().Where(f => f.UserId == _authService.UserId).Cast<SiteData>();
return Task.FromResult(data.Select(s => new Site(s)));
} }
public async Task SaveAsync(Site site) public async Task SaveAsync(Site site)
{ {
var data = new SiteData(site); var data = new SiteData(site, _authService.UserId);
data.RevisionDateTime = DateTime.UtcNow; data.RevisionDateTime = DateTime.UtcNow;
if(site.Id == 0) if(site.Id == 0)

View file

@ -7,6 +7,7 @@
<package id="sqlite-net-pcl" version="1.1.1" targetFramework="portable45-net45+win8+wpa81" /> <package id="sqlite-net-pcl" version="1.1.1" targetFramework="portable45-net45+win8+wpa81" />
<package id="SQLitePCL.raw" version="0.8.6" targetFramework="portable45-net45+win8+wpa81" /> <package id="SQLitePCL.raw" version="0.8.6" targetFramework="portable45-net45+win8+wpa81" />
<package id="Unity" version="3.5.1405-prerelease" targetFramework="portable45-net45+win8+wpa81" /> <package id="Unity" version="3.5.1405-prerelease" targetFramework="portable45-net45+win8+wpa81" />
<package id="Xam.Plugins.Settings" version="2.1.0" targetFramework="portable45-net45+win8+wpa81" />
<package id="Xamarin.Forms" version="2.2.0.31" targetFramework="portable45-net45+win8+wpa81" /> <package id="Xamarin.Forms" version="2.2.0.31" targetFramework="portable45-net45+win8+wpa81" />
<package id="XLabs.IoC" version="2.0.5782" targetFramework="portable45-net45+win8+wpa81" /> <package id="XLabs.IoC" version="2.0.5782" targetFramework="portable45-net45+win8+wpa81" />
</packages> </packages>

View file

@ -10,6 +10,7 @@ using Bit.App.Abstractions;
using Bit.App.Services; using Bit.App.Services;
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity;
using Bit.iOS.Services; using Bit.iOS.Services;
using Plugin.Settings;
namespace Bit.iOS namespace Bit.iOS
{ {
@ -48,6 +49,7 @@ namespace Bit.iOS
.RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager()) .RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager())
.RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager()) .RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager())
.RegisterType<ISecureStorageService, KeyChainStorageService>(new ContainerControlledLifetimeManager()) .RegisterType<ISecureStorageService, KeyChainStorageService>(new ContainerControlledLifetimeManager())
.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager())
.RegisterType<IApiService, ApiService>(new ContainerControlledLifetimeManager()) .RegisterType<IApiService, ApiService>(new ContainerControlledLifetimeManager())
.RegisterType<ICryptoService, CryptoService>(new ContainerControlledLifetimeManager()) .RegisterType<ICryptoService, CryptoService>(new ContainerControlledLifetimeManager())
.RegisterType<IAuthService, AuthService>(new ContainerControlledLifetimeManager()) .RegisterType<IAuthService, AuthService>(new ContainerControlledLifetimeManager())

View file

@ -130,6 +130,14 @@
<HintPath>..\..\packages\modernhttpclient.2.4.2\lib\Xamarin.iOS10\ModernHttpClient.dll</HintPath> <HintPath>..\..\packages\modernhttpclient.2.4.2\lib\Xamarin.iOS10\ModernHttpClient.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Plugin.Settings, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\Xamarin.iOS10\Plugin.Settings.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Plugin.Settings.Abstractions, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SQLite-net, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath> <HintPath>..\..\packages\sqlite-net-pcl.1.1.1\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View file

@ -5,6 +5,7 @@
<package id="sqlite-net-pcl" version="1.1.1" targetFramework="xamarinios10" /> <package id="sqlite-net-pcl" version="1.1.1" targetFramework="xamarinios10" />
<package id="SQLitePCL.raw" version="0.8.6" targetFramework="xamarinios10" /> <package id="SQLitePCL.raw" version="0.8.6" targetFramework="xamarinios10" />
<package id="Unity" version="3.5.1405-prerelease" targetFramework="xamarinios10" /> <package id="Unity" version="3.5.1405-prerelease" targetFramework="xamarinios10" />
<package id="Xam.Plugins.Settings" version="2.1.0" targetFramework="xamarinios10" />
<package id="Xamarin.Forms" version="2.2.0.31" targetFramework="xamarinios10" /> <package id="Xamarin.Forms" version="2.2.0.31" targetFramework="xamarinios10" />
<package id="XLabs.IoC" version="2.0.5782" targetFramework="xamarinios10" /> <package id="XLabs.IoC" version="2.0.5782" targetFramework="xamarinios10" />
<package id="XLabs.IoC.Unity" version="2.0.5782" targetFramework="xamarinios10" /> <package id="XLabs.IoC.Unity" version="2.0.5782" targetFramework="xamarinios10" />