mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
Compare commits
74 Commits
maui-singl
...
auth/pm-22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdc05d3cdf | ||
|
|
c25906206e | ||
|
|
148b2ad048 | ||
|
|
6edac4f296 | ||
|
|
5fda15bbc7 | ||
|
|
d3023c101b | ||
|
|
dfc7c55b77 | ||
|
|
7901931899 | ||
|
|
8ff79d0e86 | ||
|
|
a938a3f0fc | ||
|
|
0f776074c8 | ||
|
|
2208ae67fb | ||
|
|
9b7dc7210f | ||
|
|
28addfeb43 | ||
|
|
13a46fae5a | ||
|
|
52aabe8237 | ||
|
|
eceee581c9 | ||
|
|
15be0f8c2e | ||
|
|
01ed99e4b1 | ||
|
|
e2841e8d89 | ||
|
|
9b02879782 | ||
|
|
dd2cd0d9df | ||
|
|
661ff3da5c | ||
|
|
cdacbafae4 | ||
|
|
acf7d9d9c4 | ||
|
|
f12cc69b60 | ||
|
|
2465a28667 | ||
|
|
080aabfe82 | ||
|
|
b7a8e0ab07 | ||
|
|
c0688c584e | ||
|
|
c09672ff88 | ||
|
|
80eec8d81e | ||
|
|
635b6bc184 | ||
|
|
da7a1964ef | ||
|
|
73b8d8e6b8 | ||
|
|
c61f9f0357 | ||
|
|
a3183857b9 | ||
|
|
bedbca841d | ||
|
|
0ff314f076 | ||
|
|
c9a7c29190 | ||
|
|
546bf8dcb1 | ||
|
|
7fdc5597fc | ||
|
|
7c664f58b3 | ||
|
|
bdfe806846 | ||
|
|
5ed567ab90 | ||
|
|
cd4f44e6f6 | ||
|
|
d58f0b281b | ||
|
|
5ba3fac0c0 | ||
|
|
1e30524985 | ||
|
|
515decb4c9 | ||
|
|
bf28d373e9 | ||
|
|
69d38d4d75 | ||
|
|
c1619536aa | ||
|
|
079e02e4e5 | ||
|
|
15d3da607b | ||
|
|
b5cf9fd79d | ||
|
|
848e620647 | ||
|
|
4e886de103 | ||
|
|
0e450904c5 | ||
|
|
5e1229f943 | ||
|
|
9b6b2c005e | ||
|
|
e9ac1e3b5b | ||
|
|
b688b85d0f | ||
|
|
a5df6c0c65 | ||
|
|
c2d4fa4429 | ||
|
|
548bd12a8e | ||
|
|
58542fd255 | ||
|
|
800b4c71de | ||
|
|
3053eaa036 | ||
|
|
6268f0776b | ||
|
|
cbbc41be67 | ||
|
|
e164fb9823 | ||
|
|
87866304a6 | ||
|
|
84a82f0876 |
@@ -4,7 +4,7 @@
|
||||
|
||||
# Bitwarden Mobile Application
|
||||
|
||||
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on Google Play" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
|
||||
|
||||
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "7.0.306"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Media;
|
||||
using Android.Nfc;
|
||||
using Android.OS;
|
||||
using Android.Provider;
|
||||
@@ -17,9 +18,14 @@ using Bit.App.Utilities;
|
||||
using Bit.App.Utilities.Prompts;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Droid.Utilities;
|
||||
using Plugin.CurrentActivity;
|
||||
using Xamarin.Forms.Platform.Android;
|
||||
using static Android.Icu.Text.CaseMap;
|
||||
using static Android.Renderscripts.ScriptGroup;
|
||||
using static Android.Util.EventLogTags;
|
||||
using static Bit.App.Pages.SettingsPageViewModel;
|
||||
|
||||
namespace Bit.Droid.Services
|
||||
{
|
||||
@@ -261,7 +267,6 @@ namespace Bit.Droid.Services
|
||||
|
||||
var result = new TaskCompletionSource<ValidatablePromptResponse?>();
|
||||
|
||||
alertBuilder.SetOnCancelListener(new BasicDialogWithResultCancelListener(result));
|
||||
alertBuilder.SetPositiveButton(config.OkButtonText ?? AppResources.Ok, listener: null);
|
||||
alertBuilder.SetNegativeButton(config.CancelButtonText ?? AppResources.Cancel, (sender, args) => result.TrySetResult(null));
|
||||
if (!string.IsNullOrEmpty(config.ThirdButtonText))
|
||||
@@ -609,20 +614,4 @@ namespace Bit.Droid.Services
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
}
|
||||
|
||||
class BasicDialogWithResultCancelListener : Java.Lang.Object, IDialogInterfaceOnCancelListener
|
||||
{
|
||||
private readonly TaskCompletionSource<ValidatablePromptResponse?> _taskCompletionSource;
|
||||
|
||||
public BasicDialogWithResultCancelListener(TaskCompletionSource<ValidatablePromptResponse?> taskCompletionSource)
|
||||
{
|
||||
_taskCompletionSource = taskCompletionSource;
|
||||
}
|
||||
|
||||
public void OnCancel(IDialogInterface dialog)
|
||||
{
|
||||
_taskCompletionSource?.TrySetResult(null);
|
||||
dialog?.Dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RootNamespace>Bit.App</RootNamespace>
|
||||
<AssemblyName>BitwardenApp</AssemblyName>
|
||||
<Configurations>Debug;Release;FDroid</Configurations>
|
||||
<TargetFrameworks>net7.0-android;net7.0-ios</TargetFrameworks>
|
||||
<UseMaui>True</UseMaui>
|
||||
<OutputType>Library</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<SingleProject>true</SingleProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Plugin.Fingerprint" Version="2.1.5" />
|
||||
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.88.3" />
|
||||
<PackageReference Include="Xamarin.CommunityToolkit" Version="2.0.6" />
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.7.5" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
|
||||
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
|
||||
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
|
||||
<PackageReference Include="MessagePack" Version="2.4.59" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Core" Version="2.88.3" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.3" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.3" />
|
||||
<PackageReference Include="CommunityToolkit.Maui" Version="5.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Pages\Accounts\EnvironmentPage.xaml.cs">
|
||||
<DependentUpon>EnvironmentPage.xaml</DependentUpon>
|
||||
@@ -125,6 +130,7 @@
|
||||
<DependentUpon>LoginPasswordlessRequestPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Behaviors\" />
|
||||
@@ -142,9 +148,11 @@
|
||||
<Folder Include="Utilities\Automation\" />
|
||||
<Folder Include="Utilities\Prompts\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="Pages\Accounts\AccountsPopupPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Styles\Black.xaml.cs">
|
||||
<DependentUpon>Black.xaml</DependentUpon>
|
||||
@@ -168,6 +176,7 @@
|
||||
<DependentUpon>Android.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\AppResources.cs.Designer.cs">
|
||||
<DependentUpon>AppResources.cs.resx</DependentUpon>
|
||||
@@ -305,6 +314,7 @@
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources\AppResources.cs.resx">
|
||||
<LastGenOutput>AppResources.cs.Designer.cs</LastGenOutput>
|
||||
@@ -415,6 +425,7 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Behaviors\" />
|
||||
<None Remove="Xamarin.CommunityToolkit" />
|
||||
@@ -434,4 +445,4 @@
|
||||
<None Remove="Utilities\Automation\" />
|
||||
<None Remove="Utilities\Prompts\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.App">
|
||||
<Application.Resources>
|
||||
|
||||
@@ -15,9 +15,8 @@ using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Response;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
namespace Bit.App
|
||||
@@ -94,7 +93,6 @@ namespace Bit.App
|
||||
}
|
||||
else if (message.Command == "resumed")
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ResumedAsync().FireAndForget();
|
||||
@@ -102,7 +100,6 @@ namespace Bit.App
|
||||
}
|
||||
else if (message.Command == "slept")
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
await SleptAsync();
|
||||
@@ -124,7 +121,7 @@ namespace Bit.App
|
||||
Options.OtpData = new OtpData((string)message.Data);
|
||||
}
|
||||
|
||||
Device.InvokeOnMainThreadAsync(async () =>
|
||||
await Device.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
if (Current.MainPage is TabsPage tabsPage)
|
||||
{
|
||||
@@ -296,7 +293,6 @@ namespace Bit.App
|
||||
{
|
||||
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
|
||||
}
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
await _vaultTimeoutService.CheckVaultTimeoutAsync();
|
||||
@@ -312,7 +308,6 @@ namespace Bit.App
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("XF App: OnSleep");
|
||||
_isResumed = false;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
var isLocked = await _vaultTimeoutService.IsLockedAsync();
|
||||
@@ -336,7 +331,6 @@ namespace Bit.App
|
||||
{
|
||||
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
|
||||
}
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ResumedAsync().FireAndForget();
|
||||
@@ -402,7 +396,6 @@ namespace Bit.App
|
||||
|
||||
private void ClearAutofillUri()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(Options.Uri))
|
||||
{
|
||||
Options.Uri = null;
|
||||
@@ -411,7 +404,6 @@ namespace Bit.App
|
||||
|
||||
private bool SetTabsPageFromAutofill(bool isLocked)
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android && !string.IsNullOrWhiteSpace(Options.Uri) &&
|
||||
!Options.FromAutofillFramework)
|
||||
{
|
||||
@@ -460,7 +452,7 @@ namespace Bit.App
|
||||
|
||||
private void SyncIfNeeded()
|
||||
{
|
||||
if (Microsoft.Maui.Networking.Connectivity.NetworkAccess == Microsoft.Maui.Networking.NetworkAccess.None)
|
||||
if (Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Behaviors
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<ContentView
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:xct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:effects="clr-namespace:Bit.App.Effects"
|
||||
xmlns:view="clr-namespace:Bit.Core.Models.View;assembly=BitwardenCore"
|
||||
|
||||
@@ -4,8 +4,7 @@ using System.Windows.Input;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -62,8 +61,7 @@ namespace Bit.App.Controls
|
||||
|
||||
public ICommand LongPressAccountCommand { get; }
|
||||
|
||||
public int AccountListRowHeight => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
Device.RuntimePlatform == Device.Android ? 74 : 70;
|
||||
public int AccountListRowHeight => Device.RuntimePlatform == Device.Android ? 74 : 70;
|
||||
|
||||
public bool LongPressAccountEnabled { get; set; } = true;
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@ using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:xct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
|
||||
x:Class="Bit.App.Controls.AccountViewCell"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.Core.Models.View;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<controls:ExtendedGrid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<controls:ExtendedGrid xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Controls.AuthenticatorViewCell"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -3,8 +3,7 @@ using Bit.App.Pages;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -5,8 +5,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Utilities;
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -161,7 +160,7 @@ namespace Bit.App.Controls
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return Color.FromArgb("#33ffffff");
|
||||
return Color.FromHex("#33ffffff");
|
||||
}
|
||||
var hash = 0;
|
||||
for (var i = 0; i < str.Length; i++)
|
||||
@@ -175,7 +174,7 @@ namespace Bit.App.Controls
|
||||
var base16 = "00" + Convert.ToString(value, 16);
|
||||
color += base16.Substring(base16.Length - 2);
|
||||
}
|
||||
return Color.FromArgb(color);
|
||||
return Color.FromHex(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<controls:ExtendedGrid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<controls:ExtendedGrid xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Controls.CipherViewCell"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -3,8 +3,7 @@ using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Bit.App.Controls
|
||||
public bool ShowIconImage
|
||||
{
|
||||
get => WebsiteIconsEnabled
|
||||
&& !string.IsNullOrWhiteSpace(Cipher.LaunchUri)
|
||||
&& !string.IsNullOrWhiteSpace(Cipher.Login?.Uri)
|
||||
&& IconImageSource != null;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Bit.App.Controls
|
||||
{
|
||||
if (_iconImageSource == string.Empty) // default value since icon source can return null
|
||||
{
|
||||
_iconImageSource = IconImageHelper.GetIconImage(Cipher);
|
||||
_iconImageSource = IconImageHelper.GetLoginIconImage(Cipher);
|
||||
}
|
||||
return _iconImageSource;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using SkiaSharp;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using SkiaSharp.Views.Maui.Controls;
|
||||
using SkiaSharp.Views.Maui;
|
||||
using SkiaSharp.Views.Forms;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -23,13 +21,13 @@ namespace Bit.App.Controls
|
||||
nameof(StrokeWidth), typeof(float), typeof(CircularProgressbarView), 3f);
|
||||
|
||||
public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create(
|
||||
nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromArgb("175DDC"));
|
||||
nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("175DDC"));
|
||||
|
||||
public static readonly BindableProperty EndingProgressColorProperty = BindableProperty.Create(
|
||||
nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromArgb("dd4b39"));
|
||||
nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("dd4b39"));
|
||||
|
||||
public static readonly BindableProperty BackgroundProgressColorProperty = BindableProperty.Create(
|
||||
nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Colors.White);
|
||||
nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.White);
|
||||
|
||||
public double Progress
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Grid
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
x:Class="Bit.App.Controls.DateTimePicker"
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using CommunityToolkit.Maui.Converters;
|
||||
using CommunityToolkit.Maui.ImageSources;
|
||||
using CommunityToolkit.Maui;
|
||||
using CommunityToolkit.Maui.Core;
|
||||
using CommunityToolkit.Maui.Layouts;
|
||||
using CommunityToolkit.Maui.Views;
|
||||
using Xamarin.CommunityToolkit.UI.Views;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Maui.Converters;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.CommunityToolkit.Converters;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Bit.App.Utilities;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -9,7 +7,6 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public ExtendedSearchBar()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
if (ThemeManager.UsingLightTheme)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedSlider : Slider
|
||||
{
|
||||
public static readonly BindableProperty ThumbBorderColorProperty = BindableProperty.Create(
|
||||
nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.FromArgb("b5b5b5"));
|
||||
nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.FromHex("b5b5b5"));
|
||||
|
||||
public Color ThumbBorderColor
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class ExtendedStepper : Stepper
|
||||
{
|
||||
public static readonly BindableProperty StepperBackgroundColorProperty = BindableProperty.Create(
|
||||
nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Colors.White);
|
||||
nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Color.White);
|
||||
|
||||
public static readonly BindableProperty StepperForegroundColorProperty = BindableProperty.Create(
|
||||
nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Colors.Black);
|
||||
nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Color.Black);
|
||||
|
||||
public Color StepperBackgroundColor
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Bit.App.Effects;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -9,7 +8,6 @@ namespace Bit.App.Controls
|
||||
public IconButton()
|
||||
{
|
||||
Padding = 0;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Bit.App.Effects;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -10,7 +9,6 @@ namespace Bit.App.Controls
|
||||
|
||||
public IconLabel()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Frame xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Frame xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Controls.IconLabelButton"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -5,10 +5,8 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -24,13 +22,13 @@ namespace Bit.App.Controls
|
||||
nameof(ButtonCommand), typeof(ICommand), typeof(IconLabelButton));
|
||||
|
||||
public static readonly BindableProperty IconLabelColorProperty = BindableProperty.Create(
|
||||
nameof(IconLabelColor), typeof(Color), typeof(IconLabelButton), Colors.White);
|
||||
nameof(IconLabelColor), typeof(Color), typeof(IconLabelButton), Color.White);
|
||||
|
||||
public static readonly BindableProperty IconLabelBackgroundColorProperty = BindableProperty.Create(
|
||||
nameof(IconLabelBackgroundColor), typeof(Color), typeof(IconLabelButton), Colors.White);
|
||||
nameof(IconLabelBackgroundColor), typeof(Color), typeof(IconLabelButton), Color.White);
|
||||
|
||||
public static readonly BindableProperty IconLabelBorderColorProperty = BindableProperty.Create(
|
||||
nameof(IconLabelBorderColor), typeof(Color), typeof(IconLabelButton), Colors.White);
|
||||
nameof(IconLabelBorderColor), typeof(Color), typeof(IconLabelButton), Color.White);
|
||||
|
||||
public IconLabelButton()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -8,7 +7,6 @@ namespace Bit.App.Controls
|
||||
public MiButton()
|
||||
{
|
||||
Padding = 0;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -7,7 +6,6 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public MiLabel()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -7,7 +6,6 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public MonoEntry()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -7,7 +6,6 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public MonoLabel()
|
||||
{
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<StackLayout
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -102,7 +100,7 @@ namespace Bit.App.Controls
|
||||
case Controls.PasswordStrengthLevel.Strong:
|
||||
return StrongColor;
|
||||
default:
|
||||
return Colors.Transparent;
|
||||
return Color.Transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<controls:ExtendedGrid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<controls:ExtendedGrid xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Controls.SendViewCell"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Bit.App.Lists.ItemViewModels.CustomFields;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.DataTemplateSelectors
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<StackLayout
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Lists.ItemLayouts.CustomFields.BooleanCustomFieldItemLayout"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemLayouts.CustomFields
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Lists.ItemLayouts.CustomFields.HiddenCustomFieldItemLayout"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemLayouts.CustomFields
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Lists.ItemLayouts.CustomFields.LinkedCustomFieldItemLayout"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemLayouts.CustomFields
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Lists.ItemLayouts.CustomFields.TextCustomFieldItemLayout"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemLayouts.CustomFields
|
||||
{
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemViewModels.CustomFields
|
||||
{
|
||||
|
||||
@@ -5,8 +5,7 @@ using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.View;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemViewModels.CustomFields
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.Core.Models.View;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Lists.ItemViewModels.CustomFields
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.Essentials;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.Accounts.DeleteAccountPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages.Accounts
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Microsoft.Maui.Networking.Connectivity.NetworkAccess == Microsoft.Maui.Networking.NetworkAccess.None)
|
||||
if (Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
AppResources.InternetConnectionRequiredTitle, AppResources.Ok);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.EnvironmentPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -3,8 +3,7 @@ using System.Threading.Tasks;
|
||||
using Bit.App.Resources;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -19,7 +18,6 @@ namespace Bit.App.Pages
|
||||
InitializeComponent();
|
||||
_vm = BindingContext as EnvironmentPageViewModel;
|
||||
_vm.Page = this;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.HintPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -13,7 +12,6 @@ namespace Bit.App.Pages
|
||||
_vm = BindingContext as HintPageViewModel;
|
||||
_vm.Page = this;
|
||||
_vm.Email = email;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task SubmitAsync()
|
||||
{
|
||||
if (Microsoft.Maui.Networking.Connectivity.NetworkAccess == Microsoft.Maui.Networking.NetworkAccess.None)
|
||||
if (Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
AppResources.InternetConnectionRequiredTitle);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.HomePage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -4,8 +4,7 @@ using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
||||
@@ -11,8 +11,8 @@ using Bit.Core.Models.Response;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -52,9 +52,9 @@ namespace Bit.App.Pages
|
||||
};
|
||||
RememberEmailCommand = new Command(() => RememberEmail = !RememberEmail);
|
||||
ContinueCommand = new AsyncCommand(ContinueToLoginStepAsync, allowsMultipleExecutions: false);
|
||||
CreateAccountCommand = new AsyncCommand(async () => Device.InvokeOnMainThreadAsync(StartRegisterAction),
|
||||
CreateAccountCommand = new AsyncCommand(async () => await Device.InvokeOnMainThreadAsync(StartRegisterAction),
|
||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||
CloseCommand = new AsyncCommand(async () => Device.InvokeOnMainThreadAsync(CloseAction),
|
||||
CloseCommand = new AsyncCommand(async () => await Device.InvokeOnMainThreadAsync(CloseAction),
|
||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||
ShowEnvironmentPickerCommand = new AsyncCommand(ShowEnvironmentPickerAsync,
|
||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.LockPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
@@ -46,7 +46,7 @@
|
||||
<StackLayout StyleClass="box">
|
||||
<Grid
|
||||
StyleClass="box-row"
|
||||
IsVisible="{Binding PinLock}"
|
||||
IsVisible="{Binding PinEnabled}"
|
||||
Padding="0, 10, 0, 0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -89,7 +89,7 @@
|
||||
<Grid
|
||||
x:Name="_passwordGrid"
|
||||
StyleClass="box-row"
|
||||
IsVisible="{Binding PinLock, Converter={StaticResource inverseBool}}"
|
||||
IsVisible="{Binding PinEnabled, Converter={StaticResource inverseBool}}"
|
||||
Padding="0, 10, 0, 0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
|
||||
@@ -6,8 +6,7 @@ using Bit.App.Utilities;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -31,7 +30,6 @@ namespace Bit.App.Pages
|
||||
_vm.Page = this;
|
||||
_vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(async () => await UnlockedAsync());
|
||||
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.Add(_moreItem);
|
||||
@@ -46,7 +44,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_vm?.PinLock ?? false)
|
||||
if (_vm?.PinEnabled ?? false)
|
||||
{
|
||||
return _pin;
|
||||
}
|
||||
@@ -56,7 +54,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task PromptBiometricAfterResumeAsync()
|
||||
{
|
||||
if (_vm.BiometricLock)
|
||||
if (_vm.BiometricEnabled)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
if (!_promptedAfterResume)
|
||||
@@ -93,13 +91,13 @@ namespace Bit.App.Pages
|
||||
|
||||
_vm.FocusSecretEntry += PerformFocusSecretEntry;
|
||||
|
||||
if (!_vm.BiometricLock)
|
||||
if (!_vm.BiometricEnabled)
|
||||
{
|
||||
RequestFocus(SecretEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_vm.UsingKeyConnector && !_vm.PinLock)
|
||||
if (_vm.UsingKeyConnector && !_vm.PinEnabled)
|
||||
{
|
||||
_passwordGrid.IsVisible = false;
|
||||
_unlockButton.IsVisible = false;
|
||||
|
||||
@@ -11,9 +11,8 @@ using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Models.Request;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using CommunityToolkit.Maui.Converters;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.CommunityToolkit.Helpers;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -34,21 +33,21 @@ namespace Bit.App.Pages
|
||||
private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>();
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IPasswordGenerationService _passwordGenerationService;
|
||||
|
||||
private IDeviceTrustCryptoService _deviceTrustCryptoService;
|
||||
private readonly ISyncService _syncService;
|
||||
private string _email;
|
||||
private string _masterPassword;
|
||||
private string _pin;
|
||||
private bool _showPassword;
|
||||
private bool _pinLock;
|
||||
private bool _biometricLock;
|
||||
private PinLockEnum _pinStatus;
|
||||
private bool _pinEnabled;
|
||||
private bool _biometricEnabled;
|
||||
private bool _biometricIntegrityValid = true;
|
||||
private bool _biometricButtonVisible;
|
||||
private bool _usingKeyConnector;
|
||||
private string _biometricButtonText;
|
||||
private string _loggedInAsText;
|
||||
private string _lockedVerifyText;
|
||||
private bool _isPinProtected;
|
||||
private bool _isPinProtectedWithKey;
|
||||
|
||||
public LockPageViewModel()
|
||||
{
|
||||
@@ -66,6 +65,8 @@ namespace Bit.App.Pages
|
||||
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||
_policyService = ServiceContainer.Resolve<IPolicyService>();
|
||||
_passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>();
|
||||
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
|
||||
_syncService = ServiceContainer.Resolve<ISyncService>();
|
||||
|
||||
PageTitle = AppResources.VerifyMasterPassword;
|
||||
TogglePasswordCommand = new Command(TogglePassword);
|
||||
@@ -101,10 +102,10 @@ namespace Bit.App.Pages
|
||||
});
|
||||
}
|
||||
|
||||
public bool PinLock
|
||||
public bool PinEnabled
|
||||
{
|
||||
get => _pinLock;
|
||||
set => SetProperty(ref _pinLock, value);
|
||||
get => _pinEnabled;
|
||||
set => SetProperty(ref _pinEnabled, value);
|
||||
}
|
||||
|
||||
public bool UsingKeyConnector
|
||||
@@ -112,10 +113,10 @@ namespace Bit.App.Pages
|
||||
get => _usingKeyConnector;
|
||||
}
|
||||
|
||||
public bool BiometricLock
|
||||
public bool BiometricEnabled
|
||||
{
|
||||
get => _biometricLock;
|
||||
set => SetProperty(ref _biometricLock, value);
|
||||
get => _biometricEnabled;
|
||||
set => SetProperty(ref _biometricEnabled, value);
|
||||
}
|
||||
|
||||
public bool BiometricIntegrityValid
|
||||
@@ -163,14 +164,18 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task InitAsync()
|
||||
{
|
||||
(_isPinProtected, _isPinProtectedWithKey) = await _vaultTimeoutService.IsPinLockSetAsync();
|
||||
PinLock = (_isPinProtected && await _stateService.GetPinProtectedKeyAsync() != null) ||
|
||||
_isPinProtectedWithKey;
|
||||
BiometricLock = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _cryptoService.HasKeyAsync();
|
||||
_pinStatus = await _vaultTimeoutService.IsPinLockSetAsync();
|
||||
|
||||
var ephemeralPinSet = await _stateService.GetUserKeyPinEphemeralAsync()
|
||||
?? await _stateService.GetPinProtectedKeyAsync();
|
||||
PinEnabled = (_pinStatus == PinLockEnum.Transient && ephemeralPinSet != null) ||
|
||||
_pinStatus == PinLockEnum.Persistent;
|
||||
|
||||
BiometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _cryptoService.HasEncryptedUserKeyAsync();
|
||||
|
||||
// Users with key connector and without biometric or pin has no MP to unlock with
|
||||
_usingKeyConnector = await _keyConnectorService.GetUsesKeyConnector();
|
||||
if (_usingKeyConnector && !(BiometricLock || PinLock))
|
||||
if (_usingKeyConnector && !(BiometricEnabled || PinEnabled))
|
||||
{
|
||||
await _vaultTimeoutService.LogOutAsync();
|
||||
return;
|
||||
@@ -189,7 +194,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
var webVaultHostname = CoreHelpers.GetHostname(webVault);
|
||||
LoggedInAsText = string.Format(AppResources.LoggedInAsOn, _email, webVaultHostname);
|
||||
if (PinLock)
|
||||
if (PinEnabled)
|
||||
{
|
||||
PageTitle = AppResources.VerifyPIN;
|
||||
LockedVerifyText = AppResources.VaultLockedPIN;
|
||||
@@ -208,7 +213,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
if (BiometricLock)
|
||||
if (BiometricEnabled)
|
||||
{
|
||||
BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync();
|
||||
if (!_biometricIntegrityValid)
|
||||
@@ -218,7 +223,6 @@ namespace Bit.App.Pages
|
||||
}
|
||||
BiometricButtonVisible = true;
|
||||
BiometricButtonText = AppResources.UseBiometricsToUnlock;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
var supportsFace = await _deviceActionService.SupportsFaceBiometricAsync();
|
||||
@@ -231,14 +235,14 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task SubmitAsync()
|
||||
{
|
||||
if (PinLock && string.IsNullOrWhiteSpace(Pin))
|
||||
if (PinEnabled && string.IsNullOrWhiteSpace(Pin))
|
||||
{
|
||||
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
||||
string.Format(AppResources.ValidationFieldRequired, AppResources.PIN),
|
||||
AppResources.Ok);
|
||||
return;
|
||||
}
|
||||
if (!PinLock && string.IsNullOrWhiteSpace(MasterPassword))
|
||||
if (!PinEnabled && string.IsNullOrWhiteSpace(MasterPassword))
|
||||
{
|
||||
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
||||
string.Format(AppResources.ValidationFieldRequired, AppResources.MasterPassword),
|
||||
@@ -249,34 +253,54 @@ namespace Bit.App.Pages
|
||||
ShowPassword = false;
|
||||
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
|
||||
|
||||
if (PinLock)
|
||||
if (PinEnabled)
|
||||
{
|
||||
var failed = true;
|
||||
try
|
||||
{
|
||||
if (_isPinProtected)
|
||||
EncString userKeyPin = null;
|
||||
EncString oldPinProtected = null;
|
||||
if (_pinStatus == PinLockEnum.Persistent)
|
||||
{
|
||||
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
||||
userKeyPin = await _stateService.GetUserKeyPinAsync();
|
||||
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
|
||||
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
|
||||
}
|
||||
else if (_pinStatus == PinLockEnum.Transient)
|
||||
{
|
||||
userKeyPin = await _stateService.GetUserKeyPinEphemeralAsync();
|
||||
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
|
||||
}
|
||||
|
||||
UserKey userKey;
|
||||
if (oldPinProtected != null)
|
||||
{
|
||||
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
|
||||
_pinStatus == PinLockEnum.Transient,
|
||||
Pin,
|
||||
_email,
|
||||
kdfConfig,
|
||||
await _stateService.GetPinProtectedKeyAsync());
|
||||
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
||||
failed = decPin != Pin;
|
||||
if (!failed)
|
||||
{
|
||||
Pin = string.Empty;
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
await SetKeyAndContinueAsync(key);
|
||||
}
|
||||
oldPinProtected
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email, kdfConfig);
|
||||
failed = false;
|
||||
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
|
||||
Pin,
|
||||
_email,
|
||||
kdfConfig,
|
||||
userKeyPin
|
||||
);
|
||||
}
|
||||
|
||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
|
||||
failed = decryptedPin != Pin;
|
||||
if (!failed)
|
||||
{
|
||||
Pin = string.Empty;
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
await SetKeyAndContinueAsync(key);
|
||||
await SetKeyAndContinueAsync(userKey);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -297,19 +321,21 @@ namespace Bit.App.Pages
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig);
|
||||
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
|
||||
var masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, _email, kdfConfig);
|
||||
var storedKeyHash = await _cryptoService.GetPasswordHashAsync();
|
||||
var passwordValid = false;
|
||||
MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null;
|
||||
|
||||
if (storedKeyHash != null)
|
||||
{
|
||||
passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, key);
|
||||
// Offline unlock possible
|
||||
passwordValid = await _cryptoService.CompareAndUpdatePasswordHashAsync(MasterPassword, masterKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Online unlock required
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
|
||||
var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
|
||||
var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.ServerAuthorization);
|
||||
var request = new PasswordVerificationRequest();
|
||||
request.MasterPasswordHash = keyHash;
|
||||
|
||||
@@ -318,8 +344,8 @@ namespace Bit.App.Pages
|
||||
var response = await _apiService.PostAccountVerifyPasswordAsync(request);
|
||||
enforcedMasterPasswordOptions = response.MasterPasswordPolicy;
|
||||
passwordValid = true;
|
||||
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
|
||||
await _cryptoService.SetKeyHashAsync(localKeyHash);
|
||||
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, masterKey, HashPurpose.LocalAuthorization);
|
||||
await _cryptoService.SetPasswordHashAsync(localKeyHash);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -329,15 +355,6 @@ namespace Bit.App.Pages
|
||||
}
|
||||
if (passwordValid)
|
||||
{
|
||||
if (_isPinProtected)
|
||||
{
|
||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
||||
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
||||
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email, kdfConfig);
|
||||
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey));
|
||||
}
|
||||
|
||||
if (await RequirePasswordChangeAsync(enforcedMasterPasswordOptions))
|
||||
{
|
||||
// Save the ForcePasswordResetReason to force a password reset after unlock
|
||||
@@ -347,10 +364,13 @@ namespace Bit.App.Pages
|
||||
|
||||
MasterPassword = string.Empty;
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
await SetKeyAndContinueAsync(key);
|
||||
|
||||
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
|
||||
await _cryptoService.SetMasterKeyAsync(masterKey);
|
||||
await SetKeyAndContinueAsync(userKey);
|
||||
|
||||
// Re-enable biometrics
|
||||
if (BiometricLock & !BiometricIntegrityValid)
|
||||
if (BiometricEnabled & !BiometricIntegrityValid)
|
||||
{
|
||||
await _biometricService.SetupBiometricAsync();
|
||||
}
|
||||
@@ -427,7 +447,7 @@ namespace Bit.App.Pages
|
||||
public void TogglePassword()
|
||||
{
|
||||
ShowPassword = !ShowPassword;
|
||||
var secret = PinLock ? Pin : MasterPassword;
|
||||
var secret = PinEnabled ? Pin : MasterPassword;
|
||||
_secretEntryFocusWeakEventManager.RaiseEvent(string.IsNullOrEmpty(secret) ? 0 : secret.Length, nameof(FocusSecretEntry));
|
||||
}
|
||||
|
||||
@@ -435,12 +455,12 @@ namespace Bit.App.Pages
|
||||
{
|
||||
BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync();
|
||||
BiometricButtonVisible = BiometricIntegrityValid;
|
||||
if (!BiometricLock || !BiometricIntegrityValid)
|
||||
if (!BiometricEnabled || !BiometricIntegrityValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
|
||||
PinLock ? AppResources.PIN : AppResources.MasterPassword,
|
||||
PinEnabled ? AppResources.PIN : AppResources.MasterPassword,
|
||||
() => _secretEntryFocusWeakEventManager.RaiseEvent((int?)null, nameof(FocusSecretEntry)));
|
||||
await _stateService.SetBiometricLockedAsync(!success);
|
||||
if (success)
|
||||
@@ -449,18 +469,20 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
|
||||
private async Task SetKeyAndContinueAsync(UserKey key)
|
||||
{
|
||||
var hasKey = await _cryptoService.HasKeyAsync();
|
||||
var hasKey = await _cryptoService.HasUserKeyAsync();
|
||||
if (!hasKey)
|
||||
{
|
||||
await _cryptoService.SetKeyAsync(key);
|
||||
await _cryptoService.SetUserKeyAsync(key);
|
||||
}
|
||||
await _deviceTrustCryptoService.TrustDeviceIfNeededAsync();
|
||||
await DoContinueAsync();
|
||||
}
|
||||
|
||||
private async Task DoContinueAsync()
|
||||
{
|
||||
_syncService.FullSyncAsync(false).FireAndForget();
|
||||
await _stateService.SetBiometricLockedAsync(false);
|
||||
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
|
||||
_messagingService.Send("unlocked");
|
||||
|
||||
76
src/App/Pages/Accounts/LoginApproveDevicePage.xaml
Normal file
76
src/App/Pages/Accounts/LoginApproveDevicePage.xaml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.LoginApproveDevicePage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
x:DataType="pages:LoginApproveDeviceViewModel"
|
||||
x:Name="_page"
|
||||
Title="{Binding PageTitle}">
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<pages:LoginApproveDeviceViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<StackLayout Padding="10, 10">
|
||||
<StackLayout Padding="5, 10" Orientation="Horizontal">
|
||||
<StackLayout HorizontalOptions="FillAndExpand">
|
||||
<Label
|
||||
StyleClass="text-md"
|
||||
Text="{u:I18n RememberThisDevice}"/>
|
||||
<Label
|
||||
StyleClass="box-sub-label"
|
||||
Text="{u:I18n TurnOffUsingPublicDevice}"/>
|
||||
</StackLayout>
|
||||
<Switch
|
||||
Scale="0.8"
|
||||
IsToggled="{Binding RememberThisDevice}"
|
||||
VerticalOptions="Center"/>
|
||||
</StackLayout>
|
||||
<StackLayout Margin="0, 20, 0, 0">
|
||||
<Button
|
||||
x:Name="_continue"
|
||||
Text="{u:I18n Continue}"
|
||||
StyleClass="btn-primary"
|
||||
Command="{Binding ContinueCommand}"
|
||||
IsVisible="{Binding ContinueEnabled}"/>
|
||||
<Button
|
||||
x:Name="_approveWithMyOtherDevice"
|
||||
Text="{u:I18n ApproveWithMyOtherDevice}"
|
||||
StyleClass="btn-primary"
|
||||
Command="{Binding ApproveWithMyOtherDeviceCommand}"
|
||||
IsVisible="{Binding ApproveWithMyOtherDeviceEnabled}"/>
|
||||
<Button
|
||||
x:Name="_requestAdminApproval"
|
||||
Text="{u:I18n RequestAdminApproval}"
|
||||
StyleClass="box-button-row"
|
||||
Command="{Binding RequestAdminApprovalCommand}"
|
||||
IsVisible="{Binding RequestAdminApprovalEnabled}"/>
|
||||
<Button
|
||||
x:Name="_approveWithMasterPassword"
|
||||
Text="{u:I18n ApproveWithMasterPassword}"
|
||||
StyleClass="box-button-row"
|
||||
Command="{Binding ApproveWithMasterPasswordCommand}"
|
||||
IsVisible="{Binding ApproveWithMasterPasswordEnabled}"/>
|
||||
<Label
|
||||
Text="{Binding LoggingInAsText}"
|
||||
StyleClass="text-sm"
|
||||
Margin="0,40,0,0"
|
||||
AutomationId="LoggingInAsLabel"
|
||||
/>
|
||||
<Label
|
||||
Text="{u:I18n NotYou}"
|
||||
StyleClass="text-md"
|
||||
HorizontalOptions="Start"
|
||||
TextColor="{DynamicResource HyperlinkColor}"
|
||||
AutomationId="NotYouLabel">
|
||||
<Label.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="Cancel_Clicked" />
|
||||
</Label.GestureRecognizers>
|
||||
</Label>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</pages:BaseContentPage>
|
||||
|
||||
|
||||
62
src/App/Pages/Accounts/LoginApproveDevicePage.xaml.cs
Normal file
62
src/App/Pages/Accounts/LoginApproveDevicePage.xaml.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
public partial class LoginApproveDevicePage : BaseContentPage
|
||||
{
|
||||
|
||||
private readonly LoginApproveDeviceViewModel _vm;
|
||||
private readonly AppOptions _appOptions;
|
||||
|
||||
public LoginApproveDevicePage(AppOptions appOptions = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
_vm = BindingContext as LoginApproveDeviceViewModel;
|
||||
_vm.LogInWithMasterPasswordAction = () => StartLogInWithMasterPassword().FireAndForget();
|
||||
_vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget();
|
||||
_vm.RequestAdminApprovalAction = () => RequestAdminApprovalAsync().FireAndForget();
|
||||
_vm.CloseAction = () => { Navigation.PopModalAsync(); };
|
||||
_vm.Page = this;
|
||||
_appOptions = appOptions;
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
_vm.InitAsync();
|
||||
}
|
||||
|
||||
private void Cancel_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (DoOnce())
|
||||
{
|
||||
_vm.CloseAction();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task StartLogInWithMasterPassword()
|
||||
{
|
||||
var page = new LockPage(_appOptions);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
|
||||
private async Task StartLoginWithDeviceAsync()
|
||||
{
|
||||
var page = new LoginPasswordlessRequestPage(_vm.Email, AuthRequestType.AuthenticateAndUnlock, _appOptions);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
|
||||
private async Task RequestAdminApprovalAsync()
|
||||
{
|
||||
var page = new LoginPasswordlessRequestPage(_vm.Email, AuthRequestType.AdminApproval, _appOptions);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
132
src/App/Pages/Accounts/LoginApproveDeviceViewModel.cs
Normal file
132
src/App/Pages/Accounts/LoginApproveDeviceViewModel.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities.AccountManagement;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Request;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
public class LoginApproveDeviceViewModel : BaseViewModel
|
||||
{
|
||||
private bool _rememberThisDevice;
|
||||
private bool _approveWithMyOtherDeviceEnabled;
|
||||
private bool _requestAdminApprovalEnabled;
|
||||
private bool _approveWithMasterPasswordEnabled;
|
||||
private bool _continueEnabled;
|
||||
private string _email;
|
||||
private readonly IStateService _stateService;
|
||||
private readonly IApiService _apiService;
|
||||
private IDeviceTrustCryptoService _deviceTrustCryptoService;
|
||||
|
||||
public ICommand ApproveWithMyOtherDeviceCommand { get; }
|
||||
public ICommand RequestAdminApprovalCommand { get; }
|
||||
public ICommand ApproveWithMasterPasswordCommand { get; }
|
||||
public ICommand ContinueCommand { get; }
|
||||
|
||||
public Action LogInWithMasterPasswordAction { get; set; }
|
||||
public Action LogInWithDeviceAction { get; set; }
|
||||
public Action RequestAdminApprovalAction { get; set; }
|
||||
public Action CloseAction { get; set; }
|
||||
|
||||
public LoginApproveDeviceViewModel()
|
||||
{
|
||||
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||
_apiService = ServiceContainer.Resolve<IApiService>();
|
||||
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
|
||||
|
||||
PageTitle = AppResources.LoggedIn;
|
||||
|
||||
ApproveWithMyOtherDeviceCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithDeviceAction),
|
||||
onException: ex => HandleException(ex),
|
||||
allowsMultipleExecutions: false);
|
||||
|
||||
RequestAdminApprovalCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(RequestAdminApprovalAction),
|
||||
onException: ex => HandleException(ex),
|
||||
allowsMultipleExecutions: false);
|
||||
|
||||
ApproveWithMasterPasswordCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithMasterPasswordAction),
|
||||
onException: ex => HandleException(ex),
|
||||
allowsMultipleExecutions: false);
|
||||
|
||||
ContinueCommand = new AsyncCommand(InitAsync,
|
||||
onException: ex => HandleException(ex),
|
||||
allowsMultipleExecutions: false);
|
||||
}
|
||||
|
||||
public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email);
|
||||
|
||||
public bool RememberThisDevice
|
||||
{
|
||||
get => _rememberThisDevice;
|
||||
set => SetProperty(ref _rememberThisDevice, value);
|
||||
}
|
||||
|
||||
public bool ApproveWithMyOtherDeviceEnabled
|
||||
{
|
||||
get => _approveWithMyOtherDeviceEnabled;
|
||||
set => SetProperty(ref _approveWithMyOtherDeviceEnabled, value);
|
||||
}
|
||||
|
||||
public bool RequestAdminApprovalEnabled
|
||||
{
|
||||
get => _requestAdminApprovalEnabled;
|
||||
set => SetProperty(ref _requestAdminApprovalEnabled, value);
|
||||
}
|
||||
|
||||
public bool ApproveWithMasterPasswordEnabled
|
||||
{
|
||||
get => _approveWithMasterPasswordEnabled;
|
||||
set => SetProperty(ref _approveWithMasterPasswordEnabled, value);
|
||||
}
|
||||
|
||||
public bool ContinueEnabled
|
||||
{
|
||||
get => _continueEnabled;
|
||||
set => SetProperty(ref _continueEnabled, value);
|
||||
}
|
||||
|
||||
public string Email
|
||||
{
|
||||
get => _email;
|
||||
set => SetProperty(ref _email, value, additionalPropertyNames:
|
||||
new string[] {
|
||||
nameof(LoggingInAsText)
|
||||
});
|
||||
}
|
||||
|
||||
public async Task InitAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Email = await _stateService.GetRememberedEmailAsync();
|
||||
var decryptOptions = await _stateService.GetAccountDecryptionOptions();
|
||||
RequestAdminApprovalEnabled = decryptOptions?.TrustedDeviceOption?.HasAdminApproval ?? false;
|
||||
ApproveWithMasterPasswordEnabled = decryptOptions?.HasMasterPassword ?? false;
|
||||
ApproveWithMyOtherDeviceEnabled = decryptOptions?.TrustedDeviceOption?.HasLoginApprovingDevice ?? false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleException(ex);
|
||||
}
|
||||
|
||||
// TODO: Change this expression to, Appear if the browser is trusted and shared the key with the app
|
||||
ContinueEnabled = !RequestAdminApprovalEnabled && !ApproveWithMasterPasswordEnabled && !ApproveWithMyOtherDeviceEnabled;
|
||||
}
|
||||
|
||||
private async Task SetDeviceTrustAndInvokeAsync(Action action)
|
||||
{
|
||||
await _deviceTrustCryptoService.SetShouldTrustDeviceAsync(RememberThisDevice);
|
||||
await Device.InvokeOnMainThreadAsync(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
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"
|
||||
|
||||
@@ -4,11 +4,11 @@ using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -49,7 +49,6 @@ namespace Bit.App.Pages
|
||||
_vm.Email = email;
|
||||
MasterPasswordEntry = _masterPassword;
|
||||
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.Add(_moreItem);
|
||||
@@ -95,7 +94,6 @@ namespace Bit.App.Pages
|
||||
RequestFocus(_masterPassword);
|
||||
_inputFocused = true;
|
||||
}
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android && !_vm.CanRemoveAccount)
|
||||
{
|
||||
ToolbarItems.Add(_removeAccount);
|
||||
@@ -138,7 +136,7 @@ namespace Bit.App.Pages
|
||||
|
||||
private async Task StartLoginWithDeviceAsync()
|
||||
{
|
||||
var page = new LoginPasswordlessRequestPage(_vm.Email, _appOptions);
|
||||
var page = new LoginPasswordlessRequestPage(_vm.Email, AuthRequestType.AuthenticateAndUnlock, _appOptions);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ using Bit.Core.Models.View;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -182,7 +181,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task LogInAsync(bool showLoading = true, bool checkForExistingAccount = false)
|
||||
{
|
||||
if (Microsoft.Maui.Networking.Connectivity.NetworkAccess == Microsoft.Maui.Networking.NetworkAccess.None)
|
||||
if (Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
AppResources.InternetConnectionRequiredTitle, AppResources.Ok);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.LoginPasswordlessPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.LoginPasswordlessRequestPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
@@ -21,17 +21,17 @@
|
||||
<StackLayout
|
||||
Padding="7, 0, 7, 20">
|
||||
<Label
|
||||
Text="{u:I18n LogInInitiated}"
|
||||
Text="{Binding Tittle}"
|
||||
FontSize="Title"
|
||||
FontAttributes="Bold"
|
||||
Margin="0,14,0,21"
|
||||
AutomationId="LogInInitiatedLabel" />
|
||||
<Label
|
||||
Text="{u:I18n ANotificationHasBeenSentToYourDevice}"
|
||||
Text="{Binding SubTittle}"
|
||||
FontSize="Small"
|
||||
Margin="0,0,0,10"/>
|
||||
<Label
|
||||
Text="{u:I18n PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice}"
|
||||
Text="{Binding Description}"
|
||||
FontSize="Small"
|
||||
Margin="0,0,0,24"/>
|
||||
<Label
|
||||
@@ -45,6 +45,7 @@
|
||||
AutomationId="FingerprintPhraseValue" />
|
||||
<Label
|
||||
Text="{u:I18n ResendNotification}"
|
||||
IsVisible="{Binding ResendNotificationVisible}"
|
||||
StyleClass="text-md"
|
||||
HorizontalOptions="Start"
|
||||
Margin="0,40,0,0"
|
||||
@@ -58,7 +59,7 @@
|
||||
Orientation="Horizontal"
|
||||
Margin="0,30,0,0">
|
||||
<Label
|
||||
Text="{u:I18n NeedAnotherOption}"
|
||||
Text="{Binding OtherOptions}"
|
||||
FontSize="Small"
|
||||
VerticalTextAlignment="End"/>
|
||||
<Label
|
||||
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Bit.Core.Enums;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -13,13 +13,14 @@ namespace Bit.App.Pages
|
||||
private LoginPasswordlessRequestViewModel _vm;
|
||||
private readonly AppOptions _appOptions;
|
||||
|
||||
public LoginPasswordlessRequestPage(string email, AppOptions appOptions = null)
|
||||
public LoginPasswordlessRequestPage(string email, AuthRequestType authRequestType, AppOptions appOptions = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
_appOptions = appOptions;
|
||||
_vm = BindingContext as LoginPasswordlessRequestViewModel;
|
||||
_vm.Page = this;
|
||||
_vm.Email = email;
|
||||
_vm.AuthRequestType = authRequestType;
|
||||
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
|
||||
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
|
||||
_vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -12,11 +13,12 @@ using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Models.Response;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -32,6 +34,9 @@ namespace Bit.App.Pages
|
||||
private IPlatformUtilsService _platformUtilsService;
|
||||
private IEnvironmentService _environmentService;
|
||||
private ILogger _logger;
|
||||
private IDeviceTrustCryptoService _deviceTrustCryptoService;
|
||||
private readonly ICryptoFunctionService _cryptoFunctionService;
|
||||
private readonly ICryptoService _cryptoService;
|
||||
|
||||
protected override II18nService i18nService => _i18nService;
|
||||
protected override IEnvironmentService environmentService => _environmentService;
|
||||
@@ -44,6 +49,7 @@ namespace Bit.App.Pages
|
||||
private string _email;
|
||||
private string _requestId;
|
||||
private string _requestAccessCode;
|
||||
private AuthRequestType _authRequestType;
|
||||
// Item1 publicKey, Item2 privateKey
|
||||
private Tuple<byte[], byte[]> _requestKeyPair;
|
||||
|
||||
@@ -57,6 +63,9 @@ namespace Bit.App.Pages
|
||||
_i18nService = ServiceContainer.Resolve<II18nService>();
|
||||
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
|
||||
_cryptoFunctionService = ServiceContainer.Resolve<ICryptoFunctionService>();
|
||||
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
||||
|
||||
PageTitle = AppResources.LogInWithAnotherDevice;
|
||||
|
||||
@@ -77,6 +86,70 @@ namespace Bit.App.Pages
|
||||
public ICommand CreatePasswordlessLoginCommand { get; }
|
||||
public ICommand CloseCommand { get; }
|
||||
|
||||
public string Tittle
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_authRequestType)
|
||||
{
|
||||
case AuthRequestType.AuthenticateAndUnlock:
|
||||
return AppResources.LogInInitiated;
|
||||
case AuthRequestType.AdminApproval:
|
||||
return AppResources.AdminApprovalRequested;
|
||||
default:
|
||||
return string.Empty;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string SubTittle
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_authRequestType)
|
||||
{
|
||||
case AuthRequestType.AuthenticateAndUnlock:
|
||||
return AppResources.ANotificationHasBeenSentToYourDevice;
|
||||
case AuthRequestType.AdminApproval:
|
||||
return AppResources.YourRequestHasBeenSentToYourAdmin;
|
||||
default:
|
||||
return string.Empty;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_authRequestType)
|
||||
{
|
||||
case AuthRequestType.AuthenticateAndUnlock:
|
||||
return AppResources.PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice;
|
||||
case AuthRequestType.AdminApproval:
|
||||
return AppResources.YouWillBeNotifiedOnceApproved;
|
||||
default:
|
||||
return string.Empty;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string OtherOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_authRequestType)
|
||||
{
|
||||
case AuthRequestType.AuthenticateAndUnlock:
|
||||
return AppResources.NeedAnotherOption;
|
||||
case AuthRequestType.AdminApproval:
|
||||
return AppResources.TroubleLoggingIn;
|
||||
default:
|
||||
return string.Empty;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string FingerprintPhrase
|
||||
{
|
||||
get => _fingerprintPhrase;
|
||||
@@ -89,6 +162,21 @@ namespace Bit.App.Pages
|
||||
set => SetProperty(ref _email, value);
|
||||
}
|
||||
|
||||
public AuthRequestType AuthRequestType
|
||||
{
|
||||
get => _authRequestType;
|
||||
set => SetProperty(ref _authRequestType, value, additionalPropertyNames: new string[]
|
||||
{
|
||||
nameof(Tittle),
|
||||
nameof(SubTittle),
|
||||
nameof(Description),
|
||||
nameof(OtherOptions),
|
||||
nameof(ResendNotificationVisible)
|
||||
});
|
||||
}
|
||||
|
||||
public bool ResendNotificationVisible => AuthRequestType == AuthRequestType.AuthenticateAndUnlock;
|
||||
|
||||
public void StartCheckLoginRequestStatus()
|
||||
{
|
||||
try
|
||||
@@ -119,14 +207,22 @@ namespace Bit.App.Pages
|
||||
|
||||
private async Task CheckLoginRequestStatus()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_requestId) || string.IsNullOrEmpty(_requestAccessCode))
|
||||
if (string.IsNullOrEmpty(_requestId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = await _authService.GetPasswordlessLoginResponseAsync(_requestId, _requestAccessCode);
|
||||
PasswordlessLoginResponse response = null;
|
||||
if (await _stateService.IsAuthenticatedAsync())
|
||||
{
|
||||
response = await _authService.GetPasswordlessLoginRequestByIdAsync(_requestId);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = await _authService.GetPasswordlessLoginResquestAsync(_requestId, _requestAccessCode);
|
||||
}
|
||||
|
||||
if (response.RequestApproved == null || !response.RequestApproved.Value)
|
||||
{
|
||||
@@ -138,6 +234,12 @@ namespace Bit.App.Pages
|
||||
var authResult = await _authService.LogInPasswordlessAsync(Email, _requestAccessCode, _requestId, _requestKeyPair.Item2, response.Key, response.MasterPasswordHash);
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
|
||||
if (authResult == null && await _stateService.IsAuthenticatedAsync())
|
||||
{
|
||||
await HandleLoginCompleteAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (await HandleCaptchaAsync(authResult.CaptchaSiteKey, authResult.CaptchaNeeded, CheckLoginRequestStatus))
|
||||
{
|
||||
return;
|
||||
@@ -153,8 +255,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
else
|
||||
{
|
||||
_syncService.FullSyncAsync(true).FireAndForget();
|
||||
LogInSuccessAction?.Invoke();
|
||||
await HandleLoginCompleteAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -164,25 +265,69 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleLoginCompleteAsync()
|
||||
{
|
||||
await _stateService.SetPendingAdminAuthRequestAsync(null);
|
||||
_syncService.FullSyncAsync(true).FireAndForget();
|
||||
LogInSuccessAction?.Invoke();
|
||||
}
|
||||
|
||||
private async Task CreatePasswordlessLoginAsync()
|
||||
{
|
||||
await Device.InvokeOnMainThreadAsync(() => _deviceActionService.ShowLoadingAsync(AppResources.Loading));
|
||||
|
||||
var response = await _authService.PasswordlessCreateLoginRequestAsync(_email);
|
||||
if (response != null)
|
||||
PasswordlessLoginResponse response = null;
|
||||
var pendingRequest = await _stateService.GetPendingAdminAuthRequestAsync();
|
||||
if (pendingRequest != null && _authRequestType == AuthRequestType.AdminApproval)
|
||||
{
|
||||
FingerprintPhrase = response.FingerprintPhrase;
|
||||
_requestId = response.Id;
|
||||
_requestAccessCode = response.RequestAccessCode;
|
||||
_requestKeyPair = response.RequestKeyPair;
|
||||
response = await _authService.GetPasswordlessLoginRequestByIdAsync(pendingRequest.Id);
|
||||
if (response == null || (response.IsAnswered && !response.RequestApproved.Value))
|
||||
{
|
||||
// handle pending auth request not valid remove it from state
|
||||
await _stateService.SetPendingAdminAuthRequestAsync(null);
|
||||
pendingRequest = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Derive pubKey from privKey in state to avoid MITM attacks
|
||||
// Also generate FingerprintPhrase locally for the same reason
|
||||
var derivedPublicKey = await _cryptoFunctionService.RsaExtractPublicKeyAsync(pendingRequest.PrivateKey);
|
||||
response.FingerprintPhrase = string.Join("-", await _cryptoService.GetFingerprintAsync(Email, derivedPublicKey));
|
||||
response.RequestKeyPair = new Tuple<byte[], byte[]>(derivedPublicKey, pendingRequest.PrivateKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (response == null)
|
||||
{
|
||||
response = await _authService.PasswordlessCreateLoginRequestAsync(_email, AuthRequestType);
|
||||
}
|
||||
|
||||
await HandlePasswordlessLoginAsync(response, pendingRequest == null && _authRequestType == AuthRequestType.AdminApproval);
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
}
|
||||
|
||||
private async Task HandlePasswordlessLoginAsync(PasswordlessLoginResponse response, bool createPendingAdminRequest)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(response));
|
||||
}
|
||||
|
||||
if (createPendingAdminRequest)
|
||||
{
|
||||
var pendingAuthRequest = new PendingAdminAuthRequest { Id = response.Id, PrivateKey = response.RequestKeyPair.Item2 };
|
||||
await _stateService.SetPendingAdminAuthRequestAsync(pendingAuthRequest);
|
||||
}
|
||||
|
||||
FingerprintPhrase = response.FingerprintPhrase;
|
||||
_requestId = response.Id;
|
||||
_requestAccessCode = response.RequestAccessCode;
|
||||
_requestKeyPair = response.RequestKeyPair;
|
||||
}
|
||||
|
||||
private void HandleException(Exception ex)
|
||||
{
|
||||
Microsoft.Maui.ApplicationModel.MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
|
||||
|
||||
@@ -13,8 +13,7 @@ using Bit.Core.Enums;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.LoginSsoPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -4,8 +4,7 @@ using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -30,11 +29,12 @@ namespace Bit.App.Pages
|
||||
_vm.SsoAuthSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await SsoAuthSuccessAsync());
|
||||
_vm.UpdateTempPasswordAction =
|
||||
() => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
|
||||
_vm.StartDeviceApprovalOptionsAction =
|
||||
() => Device.BeginInvokeOnMainThread(async () => await StartDeviceApprovalOptionsAsync());
|
||||
_vm.CloseAction = async () =>
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
};
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
@@ -108,10 +108,17 @@ namespace Bit.App.Pages
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
|
||||
private async Task StartDeviceApprovalOptionsAsync()
|
||||
{
|
||||
var page = new LoginApproveDevicePage();
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
|
||||
private async Task SsoAuthSuccessAsync()
|
||||
{
|
||||
RestoreAppOptionsFromCopy();
|
||||
await AppHelpers.ClearPreviousPage();
|
||||
|
||||
if (await _vaultTimeoutService.IsLockedAsync())
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new LockPage(_appOptions));
|
||||
|
||||
@@ -9,8 +9,10 @@ using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.CommunityToolkit.ObjectModel;
|
||||
using Xamarin.Essentials;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -28,6 +30,8 @@ namespace Bit.App.Pages
|
||||
private readonly IStateService _stateService;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IDeviceTrustCryptoService _deviceTrustCryptoService;
|
||||
private readonly ICryptoService _cryptoService;
|
||||
|
||||
private string _orgIdentifier;
|
||||
|
||||
@@ -44,7 +48,8 @@ namespace Bit.App.Pages
|
||||
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||
_organizationService = ServiceContainer.Resolve<IOrganizationService>();
|
||||
|
||||
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
|
||||
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
||||
|
||||
PageTitle = AppResources.Bitwarden;
|
||||
LogInCommand = new AsyncCommand(LogInAsync, allowsMultipleExecutions: false);
|
||||
@@ -60,6 +65,7 @@ namespace Bit.App.Pages
|
||||
public Action StartTwoFactorAction { get; set; }
|
||||
public Action StartSetPasswordAction { get; set; }
|
||||
public Action SsoAuthSuccessAction { get; set; }
|
||||
public Action StartDeviceApprovalOptionsAction { get; set; }
|
||||
public Action CloseAction { get; set; }
|
||||
public Action UpdateTempPasswordAction { get; set; }
|
||||
|
||||
@@ -196,6 +202,7 @@ namespace Bit.App.Pages
|
||||
try
|
||||
{
|
||||
var response = await _authService.LogInSsoAsync(code, codeVerifier, REDIRECT_URI, orgId);
|
||||
var decryptOptions = await _stateService.GetAccountDecryptionOptions();
|
||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||
await _stateService.SetRememberedOrgIdentifierAsync(OrgIdentifier);
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
@@ -211,9 +218,31 @@ namespace Bit.App.Pages
|
||||
{
|
||||
UpdateTempPasswordAction?.Invoke();
|
||||
}
|
||||
else if (decryptOptions?.TrustedDeviceOption != null)
|
||||
{
|
||||
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
||||
if (!decryptOptions.HasMasterPassword &&
|
||||
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
||||
{
|
||||
StartSetPasswordAction?.Invoke();
|
||||
}
|
||||
else if (response.ForcePasswordReset)
|
||||
{
|
||||
UpdateTempPasswordAction?.Invoke();
|
||||
}
|
||||
else if (await _deviceTrustCryptoService.IsDeviceTrustedAsync())
|
||||
{
|
||||
_syncService.FullSyncAsync(true).FireAndForget();
|
||||
SsoAuthSuccessAction?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
StartDeviceApprovalOptionsAction?.Invoke();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var task = Task.Run(async () => await _syncService.FullSyncAsync(true));
|
||||
_syncService.FullSyncAsync(true).FireAndForget();
|
||||
SsoAuthSuccessAction?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<pages:BaseContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.App.Pages.RegisterPage"
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -23,7 +22,6 @@ namespace Bit.App.Pages
|
||||
};
|
||||
MasterPasswordEntry = _masterPassword;
|
||||
ConfirmMasterPasswordEntry = _confirmMasterPassword;
|
||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
||||
if (Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
|
||||
@@ -13,8 +13,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Request;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -119,7 +118,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task SubmitAsync(bool showLoading = true)
|
||||
{
|
||||
if (Microsoft.Maui.Networking.Connectivity.NetworkAccess == Microsoft.Maui.Networking.NetworkAccess.None)
|
||||
if (Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
AppResources.InternetConnectionRequiredTitle, AppResources.Ok);
|
||||
@@ -178,25 +177,28 @@ namespace Bit.App.Pages
|
||||
Name = string.IsNullOrWhiteSpace(Name) ? null : Name;
|
||||
Email = Email.Trim().ToLower();
|
||||
var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null);
|
||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdfConfig);
|
||||
var encKey = await _cryptoService.MakeEncKeyAsync(key);
|
||||
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key);
|
||||
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
|
||||
var newMasterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, Email, kdfConfig);
|
||||
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(
|
||||
newMasterKey,
|
||||
await _cryptoService.MakeUserKeyAsync()
|
||||
);
|
||||
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, newMasterKey);
|
||||
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
||||
var request = new RegisterRequest
|
||||
{
|
||||
Email = Email,
|
||||
Name = Name,
|
||||
MasterPasswordHash = hashedPassword,
|
||||
MasterPasswordHint = Hint,
|
||||
Key = encKey.Item2.EncryptedString,
|
||||
Key = newProtectedUserKey.EncryptedString,
|
||||
Kdf = kdfConfig.Type,
|
||||
KdfIterations = kdfConfig.Iterations,
|
||||
KdfMemory = kdfConfig.Memory,
|
||||
KdfParallelism = kdfConfig.Parallelism,
|
||||
Keys = new KeysRequest
|
||||
{
|
||||
PublicKey = keys.Item1,
|
||||
EncryptedPrivateKey = keys.Item2.EncryptedString
|
||||
PublicKey = newPublicKey,
|
||||
EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString
|
||||
},
|
||||
CaptchaResponse = _captchaToken,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user