login page

This commit is contained in:
Kyle Spearrin 2019-04-19 09:42:55 -04:00
parent b3c67bab92
commit 6288a06b49
9 changed files with 171 additions and 3 deletions

View file

@ -21,6 +21,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Pages\Accounts\LoginPage.xaml.cs">
<DependentUpon>LoginPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\GeneratorPage.xaml.cs"> <Compile Update="Pages\GeneratorPage.xaml.cs">
<DependentUpon>GeneratorPage.xaml</DependentUpon> <DependentUpon>GeneratorPage.xaml</DependentUpon>
</Compile> </Compile>
@ -37,7 +40,6 @@
<ItemGroup> <ItemGroup>
<Folder Include="Resources\" /> <Folder Include="Resources\" />
<Folder Include="Pages\Accounts\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -16,11 +16,13 @@ namespace Bit.App
public partial class App : Application public partial class App : Application
{ {
private readonly MobileI18nService _i18nService; private readonly MobileI18nService _i18nService;
private readonly IUserService _userService;
private readonly IBroadcasterService _broadcasterService; private readonly IBroadcasterService _broadcasterService;
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
public App() public App()
{ {
_userService = ServiceContainer.Resolve<IUserService>("userService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService"); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService"); _messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService") as MobileI18nService; _i18nService = ServiceContainer.Resolve<II18nService>("i18nService") as MobileI18nService;
@ -29,6 +31,17 @@ namespace Bit.App
SetCulture(); SetCulture();
ThemeManager.SetTheme("light"); ThemeManager.SetTheme("light");
MainPage = new HomePage(); MainPage = new HomePage();
_userService.IsAuthenticatedAsync().ContinueWith(async authed =>
{
if(await authed)
{
Current.MainPage = new TabsPage();
}
else
{
Current.MainPage = new HomePage();
}
});
ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init(); ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init();
_broadcasterService.Subscribe<DialogDetails>("showDialog", async (details) => _broadcasterService.Subscribe<DialogDetails>("showDialog", async (details) =>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Pages.LoginPage"
xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:i18n="clr-namespace:Bit.App.Utilities"
xmlns:bv="clr-namespace:Bit.App.Controls.BoxedView"
x:DataType="pages:LoginPageViewModel"
Title="{Binding PageTitle}">
<ContentPage.BindingContext>
<pages:LoginPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Icon="cogs.png" Text="{i18n:Translate LogIn}" Clicked="LogIn_Clicked" />
</ContentPage.ToolbarItems>
<StackLayout>
<bv:BoxedView HasUnevenRows="True" VerticalOptions="Start">
<bv:BoxedSection HeaderHeight="0">
<bv:EntryCell Title="{i18n:Translate EmailAddress}"
ValueText="{Binding Email}" />
<bv:EntryCell Title="{i18n:Translate MasterPassword}"
ValueText="{Binding MasterPassword}"
IsPassword="True"
Button1Icon="cogs"
Button1Command="{Binding ShowPasswordCommand}" />
</bv:BoxedSection>
</bv:BoxedView>
<Button Text="{i18n:Translate GetPasswordHint}" VerticalOptions="EndAndExpand"></Button>
</StackLayout>
</ContentPage>

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Bit.App.Pages
{
public partial class LoginPage : ContentPage
{
private LoginPageViewModel _vm;
public LoginPage()
{
InitializeComponent();
_vm = BindingContext as LoginPageViewModel;
_vm.Page = this;
}
private async void LogIn_Clicked(object sender, EventArgs e)
{
await _vm.LogInAsync();
}
}
}

View file

@ -0,0 +1,75 @@
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Utilities;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class LoginPageViewModel : BaseViewModel
{
private readonly IDeviceActionService _deviceActionService;
private readonly IAuthService _authService;
public LoginPageViewModel()
{
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_authService = ServiceContainer.Resolve<IAuthService>("authService");
PageTitle = AppResources.Bitwarden;
ShowPasswordCommand = new Command(() =>
Page.DisplayAlert("Button 1 Command", "Button 1 message", "Cancel"));
}
public ICommand ShowPasswordCommand { get; }
public string Email { get; set; }
public string MasterPassword { get; set; }
public async Task LogInAsync()
{
if(string.IsNullOrWhiteSpace(Email))
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
string.Format(AppResources.ValidationFieldRequired, AppResources.EmailAddress),
AppResources.Ok);
return;
}
if(!Email.Contains("@"))
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.InvalidEmail, AppResources.Ok);
return;
}
if(string.IsNullOrWhiteSpace(MasterPassword))
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
string.Format(AppResources.ValidationFieldRequired, AppResources.MasterPassword),
AppResources.Ok);
return;
}
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.LoggingIn);
var response = await _authService.LogInAsync(Email, MasterPassword);
await _deviceActionService.HideLoadingAsync();
// TODO: remember email?
if(response.TwoFactor)
{
// TODO: 2fa page
}
else
{
Application.Current.MainPage = new TabsPage();
}
}
catch(ApiException e)
{
await _deviceActionService.HideLoadingAsync();
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok);
}
}
}
}

View file

@ -23,7 +23,7 @@
class="text-lg" class="text-lg"
HorizontalTextAlignment="Center"></Label> HorizontalTextAlignment="Center"></Label>
<Button Text="{i18n:Translate LogIn}" <Button Text="{i18n:Translate LogIn}"
android:Button.UseDefaultShadow="false"></Button> Clicked="LogIn_Clicked"></Button>
<Button Text="{i18n:Translate CreateAccount}"></Button> <Button Text="{i18n:Translate CreateAccount}"></Button>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>

View file

@ -14,5 +14,10 @@ namespace Bit.App.Pages
{ {
InitializeComponent(); InitializeComponent();
} }
private void LogIn_Clicked(object sender, EventArgs e)
{
Navigation.PushModalAsync(new NavigationPage(new LoginPage()));
}
} }
} }

View file

@ -19,7 +19,7 @@ namespace Bit.App.Resources {
// class via a tool like ResGen or Visual Studio. // class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class AppResources { internal class AppResources {
@ -1788,6 +1788,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Invalid email address..
/// </summary>
internal static string InvalidEmail {
get {
return ResourceManager.GetString("InvalidEmail", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Invalid Master Password. Try again.. /// Looks up a localized string similar to Invalid Master Password. Try again..
/// </summary> /// </summary>

View file

@ -1346,4 +1346,7 @@
<data name="BitwardenAutofillAlert" xml:space="preserve"> <data name="BitwardenAutofillAlert" xml:space="preserve">
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Tools" screen.</value> <value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Tools" screen.</value>
</data> </data>
<data name="InvalidEmail" xml:space="preserve">
<value>Invalid email address.</value>
</data>
</root> </root>