mirror of
https://github.com/bitwarden/importer.git
synced 2025-12-10 11:05:39 -06:00
importer app
This commit is contained in:
parent
ed7ece0f00
commit
4072b9df7b
217
.gitignore
vendored
Normal file
217
.gitignore
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studo 2015 cache/options directory
|
||||
.vs/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
PublishProfiles/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
*.[Cc]ache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Other
|
||||
project.lock.json
|
||||
*.jfm
|
||||
mail_dist/
|
||||
*.refactorlog
|
||||
*.scmp
|
||||
src/Core/Properties/launchSettings.json
|
||||
*.override.env
|
||||
**/*.DS_Store
|
||||
src/Admin/wwwroot/lib
|
||||
src/Admin/wwwroot/css
|
||||
.vscode/*
|
||||
**/.vscode/*
|
||||
bitwarden_license/src/Sso/wwwroot/lib
|
||||
bitwarden_license/src/Sso/wwwroot/css
|
||||
.github/test/build.secrets
|
||||
**/CoverageOutput/
|
||||
.idea/*
|
||||
**/**.swp
|
||||
14
Importer/App.xaml
Normal file
14
Importer/App.xaml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:Bit.Importer"
|
||||
x:Class="Bit.Importer.App">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
22
Importer/App.xaml.cs
Normal file
22
Importer/App.xaml.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace Bit.Importer;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
// Uncomment below to force light theme
|
||||
// Current.UserAppTheme = AppTheme.Light;
|
||||
InitializeComponent();
|
||||
|
||||
MainPage = new AppShell();
|
||||
}
|
||||
|
||||
protected override Window CreateWindow(IActivationState activationState)
|
||||
{
|
||||
var window = base.CreateWindow(activationState);
|
||||
window.Width = 650;
|
||||
window.Height = 1100;
|
||||
window.Title = "Bitwarden Importer";
|
||||
return window;
|
||||
}
|
||||
}
|
||||
15
Importer/AppShell.xaml
Normal file
15
Importer/AppShell.xaml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Shell
|
||||
x:Class="Bit.Importer.AppShell"
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:Bit.Importer"
|
||||
Shell.FlyoutBehavior="Disabled">
|
||||
|
||||
<ShellContent
|
||||
Title="Bitwarden Importer"
|
||||
Icon="icon.svg"
|
||||
ContentTemplate="{DataTemplate local:MainPage}"
|
||||
Route="MainPage" />
|
||||
|
||||
</Shell>
|
||||
9
Importer/AppShell.xaml.cs
Normal file
9
Importer/AppShell.xaml.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Bit.Importer;
|
||||
|
||||
public partial class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
62
Importer/Importer.csproj
Normal file
62
Importer/Importer.csproj
Normal file
@ -0,0 +1,62 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0-maccatalyst</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Bit.Importer</RootNamespace>
|
||||
<UseMaui>true</UseMaui>
|
||||
<SingleProject>true</SingleProject>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
<!-- Display name -->
|
||||
<ApplicationTitle>Bitwarden Importer</ApplicationTitle>
|
||||
|
||||
<!-- App Identifier -->
|
||||
<ApplicationId>com.bitwarden.importer</ApplicationId>
|
||||
<ApplicationIdGuid>c5a31c67-9745-473c-b2ac-cd797bf4615b</ApplicationIdGuid>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Workaround from here: https://github.com/dotnet/maui/issues/12080#issuecomment-1398635826 -->
|
||||
<PropertyGroup>
|
||||
<WindowsAppSdkDeploymentManagerInitialize>false</WindowsAppSdkDeploymentManagerInitialize>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#175DDC" />
|
||||
|
||||
<!-- Splash Screen -->
|
||||
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#175DDC" BaseSize="128,128" />
|
||||
|
||||
<!-- Images -->
|
||||
<MauiImage Include="Resources\Images\*" />
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<MauiFont Include="Resources\Fonts\*" />
|
||||
|
||||
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\Images\icon.svg" />
|
||||
<None Remove="Resources\Raw\bw-cli\bw-mac" />
|
||||
<None Remove="Resources\Raw\bw-cli\bw-windows.exe" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
<PackageReference Include="PasswordManagerAccess" Version="10.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
148
Importer/MainPage.xaml
Normal file
148
Importer/MainPage.xaml
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Bit.Importer.MainPage">
|
||||
|
||||
<ScrollView>
|
||||
<VerticalStackLayout
|
||||
Spacing="50"
|
||||
Padding="20"
|
||||
VerticalOptions="Start">
|
||||
|
||||
<VerticalStackLayout
|
||||
Spacing="10"
|
||||
Padding="0">
|
||||
<Label
|
||||
Text="The Bitwarden Importer Tool helps you easily move all of your data from an existing password management service into your Bitwarden account. Simply imput your credentials for Bitwarden and your old password management service into the form below and click the 'Import' button." />
|
||||
<Label
|
||||
Text="Click here to learn more"
|
||||
TextColor="{StaticResource Primary}"
|
||||
FontAttributes="Bold"
|
||||
TextDecorations="Underline"
|
||||
x:Name="LearnMore" />
|
||||
</VerticalStackLayout>
|
||||
|
||||
<VerticalStackLayout
|
||||
Spacing="20"
|
||||
Padding="0">
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<Label
|
||||
Text="Bitwarden Server Url" />
|
||||
<Entry
|
||||
x:Name="BitwardenServerUrl" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<HorizontalStackLayout
|
||||
Spacing="10">
|
||||
<Label
|
||||
Text="Bitwarden API Key client_id" />
|
||||
<Label
|
||||
Text="Click here to get your API key"
|
||||
TextColor="{StaticResource Primary}"
|
||||
FontAttributes="Bold"
|
||||
TextDecorations="Underline"
|
||||
x:Name="ApiKeyLink1" />
|
||||
</HorizontalStackLayout>
|
||||
<Entry
|
||||
x:Name="BitwardenApiKeyClientId" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<HorizontalStackLayout
|
||||
Spacing="10">
|
||||
<Label
|
||||
Text="Bitwarden API Key secret" />
|
||||
<Label
|
||||
Text="Click here to get your API key"
|
||||
TextColor="{StaticResource Primary}"
|
||||
FontAttributes="Bold"
|
||||
TextDecorations="Underline"
|
||||
x:Name="ApiKeyLink2"/>
|
||||
</HorizontalStackLayout>
|
||||
<Entry
|
||||
x:Name="BitwardenApiKeySecret"
|
||||
IsPassword="True" />
|
||||
</VerticalStackLayout>
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0"
|
||||
x:Name="BitwardenPasswordLayout">
|
||||
<Label
|
||||
Text="Bitwarden Master Password" />
|
||||
<Entry
|
||||
x:Name="BitwardenPassword"
|
||||
IsPassword="True" />
|
||||
</VerticalStackLayout>
|
||||
<HorizontalStackLayout
|
||||
x:Name="BitwardenKeyConnectorLayout">
|
||||
<CheckBox
|
||||
x:Name="BitwardenKeyConnector"
|
||||
CheckedChanged="BitwardenKeyConnector_CheckedChanged"
|
||||
VerticalOptions="Center" />
|
||||
<Label
|
||||
x:Name="BitwardenKeyConnectorLabel"
|
||||
Text="My organization uses a SSO configuration that does not require a master password."
|
||||
VerticalOptions="Center" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<VerticalStackLayout
|
||||
Spacing="20"
|
||||
Padding="0">
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<Label
|
||||
Text="Import From Service" />
|
||||
<Picker
|
||||
x:Name="Service" />
|
||||
</VerticalStackLayout>
|
||||
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<Label
|
||||
Text="LastPass Email" />
|
||||
<Entry
|
||||
x:Name="LastPassEmail" />
|
||||
</VerticalStackLayout>
|
||||
|
||||
<VerticalStackLayout
|
||||
Spacing="5"
|
||||
Padding="0">
|
||||
<Label
|
||||
Text="LastPass Master Password" />
|
||||
<Entry
|
||||
x:Name="LastPassPassword"
|
||||
IsPassword="True" />
|
||||
</VerticalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<HorizontalStackLayout
|
||||
Spacing="10"
|
||||
Padding="0">
|
||||
<Button
|
||||
x:Name="SubmitButton"
|
||||
Text="Import"
|
||||
Clicked="OnButtonClicked"
|
||||
HorizontalOptions="Center" />
|
||||
<ActivityIndicator
|
||||
x:Name="Loading"
|
||||
IsRunning="false"
|
||||
VerticalOptions="Center" />
|
||||
<Label
|
||||
x:Name="PleaseWait"
|
||||
Text="Please wait..."
|
||||
IsVisible="false"
|
||||
VerticalOptions="Center" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
</ContentPage>
|
||||
307
Importer/MainPage.xaml.cs
Normal file
307
Importer/MainPage.xaml.cs
Normal file
@ -0,0 +1,307 @@
|
||||
using CsvHelper;
|
||||
using PasswordManagerAccess.LastPass;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Bit.Importer;
|
||||
|
||||
public partial class MainPage : ContentPage
|
||||
{
|
||||
private readonly List<string> _services = new() { "LastPass" };
|
||||
private string _bitwardenCloudUrl = "https://bitwarden.com";
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BitwardenServerUrl.Text = _bitwardenCloudUrl;
|
||||
Service.ItemsSource = _services;
|
||||
Service.SelectedIndex = 0;
|
||||
|
||||
var learnMoreTap = new TapGestureRecognizer();
|
||||
learnMoreTap.Tapped += async (s, e) =>
|
||||
{
|
||||
await Browser.Default.OpenAsync(new Uri("https://bitwarden.com/help"),
|
||||
BrowserLaunchMode.SystemPreferred);
|
||||
};
|
||||
LearnMore.GestureRecognizers.Add(learnMoreTap);
|
||||
|
||||
var apiKeyTap = new TapGestureRecognizer();
|
||||
apiKeyTap.Tapped += async (s, e) =>
|
||||
{
|
||||
await Browser.Default.OpenAsync(new Uri("https://vault.bitwarden.com/#/settings/security/security-keys"),
|
||||
BrowserLaunchMode.SystemPreferred);
|
||||
};
|
||||
ApiKeyLink1.GestureRecognizers.Add(apiKeyTap);
|
||||
ApiKeyLink2.GestureRecognizers.Add(apiKeyTap);
|
||||
}
|
||||
|
||||
private void BitwardenKeyConnector_CheckedChanged(object sender, CheckedChangedEventArgs e)
|
||||
{
|
||||
// We don't need master passwqord if using key connector
|
||||
BitwardenPasswordLayout.IsVisible = !BitwardenKeyConnector.IsChecked;
|
||||
}
|
||||
|
||||
private async void OnButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
// Validate
|
||||
if (!await ValidateInputsAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start loading state
|
||||
Loading.IsRunning = true;
|
||||
SubmitButton.IsEnabled = false;
|
||||
PleaseWait.IsVisible = true;
|
||||
|
||||
// Run the import task
|
||||
await Task.Run(ImportAsync);
|
||||
}
|
||||
|
||||
private async Task<bool> ValidateInputsAsync()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(BitwardenApiKeyClientId?.Text) ||
|
||||
string.IsNullOrWhiteSpace(BitwardenApiKeySecret?.Text))
|
||||
{
|
||||
await DisplayAlert("Error", "Bitwarden API Key information is required.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(BitwardenPassword?.Text) &&
|
||||
!BitwardenKeyConnector.IsChecked)
|
||||
{
|
||||
await DisplayAlert("Error", "Bitwarden master password is required.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_services[Service.SelectedIndex] == "LastPass")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(LastPassEmail?.Text) ||
|
||||
string.IsNullOrWhiteSpace(LastPassPassword?.Text))
|
||||
{
|
||||
await DisplayAlert("Error", "LastPass Email and Master Password are required.", "OK");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ImportAsync()
|
||||
{
|
||||
await CleanupAsync();
|
||||
|
||||
if (_services[Service.SelectedIndex] == "LastPass")
|
||||
{
|
||||
var (lastpassSuccess, lastpassCsvPath) = await CreateLastpassCsvAsync();
|
||||
if (!lastpassSuccess)
|
||||
{
|
||||
StopLoadingAndAlert(true,
|
||||
"Unable to log into your LastPass account. Are your credentials correct?");
|
||||
}
|
||||
|
||||
var cliSetupSuccess = false;
|
||||
try
|
||||
{
|
||||
if (lastpassSuccess)
|
||||
{
|
||||
await SetupCliAsync();
|
||||
cliSetupSuccess = true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
StopLoadingAndAlert(true, "Unable to set up Bitwarden CLI.");
|
||||
}
|
||||
|
||||
if (cliSetupSuccess && lastpassSuccess)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(BitwardenServerUrl?.Text) && BitwardenServerUrl.Text != "https://bitwarden.com")
|
||||
{
|
||||
var configServerSuccess = ConfigServerCli();
|
||||
if (!configServerSuccess)
|
||||
{
|
||||
StopLoadingAndAlert(true, "Unable to configure Bitwarden server.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var (loginSuccess, sessionKey) = LogInCli();
|
||||
if (!loginSuccess)
|
||||
{
|
||||
StopLoadingAndAlert(true,
|
||||
"Unable to log into your Bitwarden account. Is your API key information correct?");
|
||||
}
|
||||
|
||||
if (loginSuccess && string.IsNullOrWhiteSpace(sessionKey))
|
||||
{
|
||||
var (unlockSuccess, unlockSessionKey) = UnlockCli();
|
||||
sessionKey = unlockSessionKey;
|
||||
if (!unlockSuccess)
|
||||
{
|
||||
StopLoadingAndAlert(true,
|
||||
"Unable to unlock your Bitwarden vault. Is your master password correct?");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(lastpassCsvPath) && !string.IsNullOrWhiteSpace(sessionKey))
|
||||
{
|
||||
var importSuccess = ImportCli("lastpasscsv", lastpassCsvPath, sessionKey);
|
||||
if (importSuccess)
|
||||
{
|
||||
StopLoadingAndAlert(false, "Your import was successful!");
|
||||
}
|
||||
else
|
||||
{
|
||||
StopLoadingAndAlert(true, "Something went wrong with the import.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await CleanupAsync();
|
||||
}
|
||||
|
||||
private void StopLoadingAndAlert(bool error, string message)
|
||||
{
|
||||
Dispatcher.Dispatch(async () =>
|
||||
{
|
||||
// Stop the loading state
|
||||
Loading.IsRunning = false;
|
||||
SubmitButton.IsEnabled = true;
|
||||
PleaseWait.IsVisible = false;
|
||||
|
||||
// Show alert
|
||||
if (error)
|
||||
{
|
||||
await DisplayAlert("Error", message, "OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
await DisplayAlert("Success", message, "OK");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<(bool, string)> CreateLastpassCsvAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Log in and get LastPass data
|
||||
var ui = new Services.LastPass.Ui(this);
|
||||
var clientInfo = new ClientInfo(
|
||||
PasswordManagerAccess.LastPass.Platform.Desktop,
|
||||
Guid.NewGuid().ToString().ToLower(),
|
||||
"Importer");
|
||||
var vault = Vault.Open(LastPassEmail?.Text, LastPassPassword?.Text, clientInfo, ui);
|
||||
|
||||
// Massage it to expected CSV format
|
||||
var exportAccounts = vault.Accounts.Select(a => new Services.LastPass.ExportedAccount(a));
|
||||
|
||||
// Create CSV string
|
||||
using var writer = new StringWriter();
|
||||
using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
|
||||
csv.WriteRecords(exportAccounts);
|
||||
csv.Flush();
|
||||
var csvOutput = writer.ToString();
|
||||
// Write CSV to temp disk
|
||||
|
||||
var lastpassCsvPath = Path.Combine(FileSystem.CacheDirectory, "lastpass-export.csv");
|
||||
await File.WriteAllTextAsync(lastpassCsvPath, csvOutput);
|
||||
return (true, lastpassCsvPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return (false, null);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ConfigServerCli()
|
||||
{
|
||||
var (exitCode, stdOut) = ExecCli($"config server {BitwardenServerUrl?.Text}");
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
private (bool, string) LogInCli()
|
||||
{
|
||||
var (exitCode, sessionKey) = ExecCli("login --apikey --raw", (process) =>
|
||||
{
|
||||
process.StartInfo.EnvironmentVariables["BW_CLIENTID"] = BitwardenApiKeyClientId?.Text;
|
||||
process.StartInfo.EnvironmentVariables["BW_CLIENTSECRET"] = BitwardenApiKeySecret?.Text;
|
||||
// Avoid BW_NOINTERACTION bug that is issuing invalid session key on api key login
|
||||
process.StartInfo.EnvironmentVariables["BW_NOINTERACTION"] = "false";
|
||||
});
|
||||
return (exitCode == 0, sessionKey);
|
||||
}
|
||||
|
||||
private (bool, string) UnlockCli()
|
||||
{
|
||||
var (exitCode, sessionKey) = ExecCli($"unlock {BitwardenPassword?.Text} --raw");
|
||||
return (exitCode == 0, sessionKey);
|
||||
}
|
||||
|
||||
private bool ImportCli(string importService, string importFilePath, string sessionKey)
|
||||
{
|
||||
var (importExitCode, importStdOut) = ExecCli($"import {importService} {importFilePath}", (process) =>
|
||||
{
|
||||
process.StartInfo.EnvironmentVariables["BW_SESSION"] = sessionKey;
|
||||
});
|
||||
return importExitCode == 0 && (importStdOut?.Contains("Imported") ?? false);
|
||||
}
|
||||
|
||||
private async Task SetupCliAsync()
|
||||
{
|
||||
// Copy packaged CLI app to disk so that we can invoke it.
|
||||
using var stream = await FileSystem.OpenAppPackageFileAsync("bw-cli/bw-windows.exe");
|
||||
using var fileStream = File.Create(ResolveCliPath());
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.CopyTo(fileStream);
|
||||
stream.Close();
|
||||
fileStream.Close();
|
||||
}
|
||||
|
||||
private (int, string) ExecCli(string args, Action<Process> processAction = null)
|
||||
{
|
||||
// Set up the process
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = ResolveCliPath(),
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
},
|
||||
};
|
||||
|
||||
// Load standard env vars for this use case
|
||||
process.StartInfo.EnvironmentVariables["BITWARDENCLI_APPDATA_DIR"] = FileSystem.CacheDirectory;
|
||||
process.StartInfo.EnvironmentVariables["BW_NOINTERACTION"] = "true";
|
||||
processAction?.Invoke(process);
|
||||
|
||||
process.Start();
|
||||
var stdOut = "";
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
stdOut += process.StandardOutput.ReadLine();
|
||||
}
|
||||
process.StandardOutput.Close();
|
||||
process.WaitForExit();
|
||||
return (process.ExitCode, stdOut.Trim());
|
||||
}
|
||||
|
||||
private string ResolveCliPath()
|
||||
{
|
||||
var bwCliFilename = DeviceInfo.Platform == DevicePlatform.WinUI ? "bw.exe" : "bw";
|
||||
return Path.Combine(FileSystem.CacheDirectory, bwCliFilename);
|
||||
}
|
||||
|
||||
private Task CleanupAsync()
|
||||
{
|
||||
File.Delete(Path.Combine(FileSystem.CacheDirectory, "data.json"));
|
||||
File.Delete(Path.Combine(FileSystem.CacheDirectory, "lastpass-export.csv"));
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
24
Importer/MauiProgram.cs
Normal file
24
Importer/MauiProgram.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Importer;
|
||||
|
||||
public static class MauiProgram
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
9
Importer/Platforms/MacCatalyst/AppDelegate.cs
Normal file
9
Importer/Platforms/MacCatalyst/AppDelegate.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Foundation;
|
||||
|
||||
namespace Bit.Importer;
|
||||
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
30
Importer/Platforms/MacCatalyst/Info.plist
Normal file
30
Importer/Platforms/MacCatalyst/Info.plist
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
15
Importer/Platforms/MacCatalyst/Program.cs
Normal file
15
Importer/Platforms/MacCatalyst/Program.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace Bit.Importer;
|
||||
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
8
Importer/Platforms/Windows/App.xaml
Normal file
8
Importer/Platforms/Windows/App.xaml
Normal file
@ -0,0 +1,8 @@
|
||||
<maui:MauiWinUIApplication
|
||||
x:Class="Bit.Importer.WinUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:maui="using:Microsoft.Maui"
|
||||
xmlns:local="using:Bit.Importer.WinUI">
|
||||
|
||||
</maui:MauiWinUIApplication>
|
||||
24
Importer/Platforms/Windows/App.xaml.cs
Normal file
24
Importer/Platforms/Windows/App.xaml.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace Bit.Importer.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : MauiWinUIApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
|
||||
46
Importer/Platforms/Windows/Package.appxmanifest
Normal file
46
Importer/Platforms/Windows/Package.appxmanifest
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="569357BF-7B0D-4BDB-B134-0D3A5765BA50" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>$placeholder$</DisplayName>
|
||||
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||
<Logo>$placeholder$.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="$placeholder$"
|
||||
Description="$placeholder$"
|
||||
Square150x150Logo="$placeholder$.png"
|
||||
Square44x44Logo="$placeholder$.png"
|
||||
BackgroundColor="transparent">
|
||||
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||
<uap:SplashScreen Image="$placeholder$.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
|
||||
</Package>
|
||||
15
Importer/Platforms/Windows/app.manifest
Normal file
15
Importer/Platforms/Windows/app.manifest
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="Importer.WinUI.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
8
Importer/Properties/launchSettings.json
Normal file
8
Importer/Properties/launchSettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Windows Machine": {
|
||||
"commandName": "MsixPackage",
|
||||
"nativeDebugging": false
|
||||
}
|
||||
}
|
||||
}
|
||||
4
Importer/Resources/AppIcon/appicon.svg
Normal file
4
Importer/Resources/AppIcon/appicon.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="456" height="456" fill="#175DDC" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
14
Importer/Resources/AppIcon/appiconfg.svg
Normal file
14
Importer/Resources/AppIcon/appiconfg.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Shield" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 390 462" style="enable-background:new 0 0 390 462;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path id="Identity" class="st0" d="M376.4,12.2c-3.7-3.7-8.1-5.6-13.1-5.6H26.7c-5.1,0-9.4,1.9-13.1,5.6C9.9,15.9,8,20.2,8,25.3
|
||||
v224.4c0,16.7,3.3,33.4,9.8,49.8c6.5,16.5,14.6,31.1,24.3,43.8c9.6,12.8,21.1,25.2,34.5,37.2c13.3,12.1,25.7,22.1,37,30.1
|
||||
c11.3,8,23.1,15.5,35.4,22.6c12.3,7.1,21,11.9,26.2,14.5c5.2,2.5,9.3,4.5,12.4,5.8c2.3,1.2,4.9,1.8,7.6,1.8c2.7,0,5.3-0.6,7.6-1.8
|
||||
c3.1-1.4,7.3-3.3,12.4-5.8c5.2-2.5,13.9-7.4,26.2-14.5c12.3-7.1,24.1-14.7,35.4-22.6c11.3-8,23.6-18,37-30.1
|
||||
c13.3-12.1,24.8-24.5,34.5-37.2c9.6-12.8,17.7-27.4,24.2-43.8c6.5-16.5,9.8-33.1,9.8-49.8V25.3C382,20.2,380.1,15.9,376.4,12.2z
|
||||
M333,251.8C333,333,195,403,195,403V54.6h138C333,54.6,333,170.6,333,251.8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Importer/Resources/Fonts/OpenSans-Regular.ttf
Normal file
BIN
Importer/Resources/Fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
BIN
Importer/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
BIN
Importer/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
Binary file not shown.
18
Importer/Resources/Images/icon.svg
Normal file
18
Importer/Resources/Images/icon.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#175DDC;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path id="Background" class="st0" d="M1024,864c0,88.4-71.6,160-160,160H160C71.6,1024,0,952.4,0,864V160C0,71.6,71.6,0,160,0h704
|
||||
c88.4,0,160,71.6,160,160V864z"/>
|
||||
<path id="Identity" class="st1" d="M829.8,128.6c-6.5-6.5-14.2-9.7-23-9.7H217.2c-8.9,0-16.5,3.2-23,9.7c-6.5,6.5-9.7,14.2-9.7,23
|
||||
v393.1c0,29.3,5.7,58.4,17.1,87.3c11.4,28.8,25.6,54.4,42.5,76.8c16.9,22.3,37,44.1,60.4,65.3c23.4,21.2,45,38.7,64.7,52.7
|
||||
c19.8,14,40.4,27.2,61.9,39.7c21.5,12.5,36.8,20.9,45.8,25.3c9,4.4,16.3,7.9,21.7,10.2c4.1,2,8.5,3.1,13.3,3.1c4.8,0,9.2-1,13.3-3.1
|
||||
c5.5-2.4,12.7-5.8,21.8-10.2c9-4.4,24.3-12.9,45.8-25.3c21.5-12.5,42.1-25.7,61.9-39.7c19.8-14,41.4-31.6,64.8-52.7
|
||||
c23.4-21.2,43.5-42.9,60.4-65.3c16.9-22.4,31-47.9,42.5-76.8c11.4-28.8,17.1-57.9,17.1-87.3V151.7
|
||||
C839.6,142.8,836.3,135.1,829.8,128.6z M753.8,548.4c0,142.3-241.8,264.9-241.8,264.9V203.1h241.8
|
||||
C753.8,203.1,753.8,406.1,753.8,548.4z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
15
Importer/Resources/Raw/AboutAssets.txt
Normal file
15
Importer/Resources/Raw/AboutAssets.txt
Normal file
@ -0,0 +1,15 @@
|
||||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories). Deployment of the asset to your application
|
||||
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
|
||||
These files will be deployed with you package and will be accessible using Essentials:
|
||||
|
||||
async Task LoadMauiAsset()
|
||||
{
|
||||
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var contents = reader.ReadToEnd();
|
||||
}
|
||||
BIN
Importer/Resources/Raw/bw-cli/bw-mac
Normal file
BIN
Importer/Resources/Raw/bw-cli/bw-mac
Normal file
Binary file not shown.
BIN
Importer/Resources/Raw/bw-cli/bw-windows.exe
Normal file
BIN
Importer/Resources/Raw/bw-cli/bw-windows.exe
Normal file
Binary file not shown.
49
Importer/Resources/Splash/splash.svg
Normal file
49
Importer/Resources/Splash/splash.svg
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 609.7 386.2" style="enable-background:new 0 0 609.7 386.2;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M44.6,307.8c8.4,0,15,3.3,19.8,9.9c4.8,6.6,7.2,15.6,7.2,27.1c0,11.8-2.5,20.9-7.4,27.4
|
||||
c-4.9,6.5-11.6,9.7-20.1,9.7c-8.4,0-15-3-19.7-9.1H23l-2.6,6.3c-0.4,0.9-1.3,1.5-2.3,1.5H7.3c-1.4,0-2.5-1.1-2.5-2.5v-94.4
|
||||
c0-1.4,1.1-2.5,2.5-2.5h14.5c1.4,0,2.5,1.1,2.5,2.5v20.6c0,2.9-0.3,7.6-0.8,14.1h0.8C28.9,311.4,35.6,307.8,44.6,307.8z M38.3,323.4
|
||||
c-4.8,0-8.3,1.5-10.5,4.4c-2.2,3-3.4,7.8-3.4,14.7v2.1c0,7.7,1.1,13.2,3.4,16.5c2.3,3.3,5.9,5,10.8,5c4,0,7.2-1.8,9.6-5.5
|
||||
c2.4-3.7,3.5-9,3.5-16.1c0-7-1.2-12.3-3.6-15.8C45.7,325.2,42.4,323.4,38.3,323.4z M103.7,380.6H89.2c-1.4,0-2.5-1.1-2.5-2.5v-66.5
|
||||
c0-1.4,1.1-2.5,2.5-2.5h14.5c1.4,0,2.5,1.1,2.5,2.5v66.5C106.2,379.5,105.1,380.6,103.7,380.6z M156.8,366.4c2.9,0,6.3-0.5,10.2-1.6
|
||||
c1.1-0.3,2.1,0.5,2.1,1.6v11.2c0,0.7-0.4,1.3-1,1.5c-4.7,1.9-10.3,2.8-16.9,2.8c-7.8,0-13.5-2-17-5.9c-3.6-3.9-5.3-9.8-5.3-17.7
|
||||
v-34.4h-7.7c-0.9,0-1.7-0.7-1.7-1.7v-6.4c0-0.1,0.1-0.3,0.2-0.4l10.5-6.4l5.2-14c0.2-0.6,0.9-1.1,1.6-1.1h9.7c0.9,0,1.7,0.7,1.7,1.7
|
||||
v13.5h19.2c0.5,0,0.8,0.4,0.8,0.8v12.1c0,0.9-0.7,1.7-1.7,1.7h-18.3v34.4c0,2.8,0.8,4.8,2.3,6.1
|
||||
C152.1,365.7,154.2,366.4,156.8,366.4z M247.2,380.6c-1.8,0-3.5-1.2-4-2.9l-14.2-43.5c-1-3.2-2.2-7.8-3.8-13.9h-0.4l-1.3,4.7
|
||||
l-2.9,9.3l-14.5,43.4c-0.6,1.7-2.2,2.9-4,2.9l0,0c-1.9,0-3.6-1.3-4.1-3.1l-17.9-62.4c-0.6-2,0.9-3.9,3-3.9h0.3c1.4,0,2.6,0.9,3,2.3
|
||||
l10.5,38c2.6,10,4.3,17.3,5.1,22h0.4c2.5-10,4.3-16.6,5.5-19.9l13.4-39.7c0.5-1.6,2.1-2.7,3.8-2.7l0,0c1.7,0,3.3,1.1,3.8,2.8
|
||||
l12.7,39.5c3.1,10,4.9,16.6,5.6,19.9h0.4c0.3-2.8,2-10.2,5.1-22.2l10-37.6c0.4-1.3,1.6-2.3,3-2.3h0c2,0,3.5,1.9,3,3.9l-16.9,62.4
|
||||
c-0.5,1.8-2.2,3.1-4.1,3.1H247.2z M326.9,380.6c-1.2,0-2.3-0.9-2.5-2.1l-1.3-8.8h-0.5c-3.5,4.5-7.1,7.6-10.8,9.5
|
||||
c-3.7,1.9-8,2.8-13.1,2.8c-6.8,0-12.1-1.7-15.9-5.2c-3.4-3.1-5.2-7.3-5.6-12.5c-0.5-6.9,2.4-13.7,8.1-17.6
|
||||
c5.7-3.9,13.9-5.9,24.8-6.1l13.2-0.4v-4.6c0-6.6-1.3-11.6-4-14.9c-2.7-3.4-7-5-13-5c-5.6,0-11.3,1.3-17.3,4c-1.5,0.7-3.3,0-3.9-1.5
|
||||
l0,0c-0.6-1.5,0.1-3.2,1.6-3.9c6.7-2.8,13.3-4.2,19.9-4.2c7.6,0,13.3,2,17.1,5.9c3.8,4,5.7,10.1,5.7,18.5v43.7
|
||||
C329.4,379.5,328.3,380.6,326.9,380.6L326.9,380.6z M299.2,376.1c7.4,0,13.3-2.1,17.5-6.4c4.3-4.2,6.4-10.1,6.4-17.7v-6.8l-12.1,0.5
|
||||
c-9.8,0.5-16.7,2-20.9,4.6c-4.2,2.6-6.2,6.6-6.2,12c0,4.3,1.3,7.7,4,10.1C290.6,374.9,294.4,376.1,299.2,376.1z M378.7,309.8
|
||||
c2,0,4.1,0.1,6.3,0.4c1.7,0.2,2.9,1.9,2.5,3.6v0c-0.3,1.6-1.9,2.6-3.5,2.4c-2-0.3-4-0.5-6.1-0.5c-5.9,0-10.8,2.5-14.6,7.5
|
||||
c-3.8,5-5.7,11.4-5.7,19v35.2c0,1.7-1.4,3.2-3.2,3.2h0c-1.7,0-3.2-1.4-3.2-3.2v-63.5c0-1.5,1.2-2.8,2.8-2.8l0,0
|
||||
c1.5,0,2.7,1.1,2.7,2.6l0.5,9.9h0.4c2.9-5.1,5.9-8.7,9.1-10.8C370.2,310.9,374.1,309.8,378.7,309.8z M425.9,309.8
|
||||
c5,0,9.4,0.9,13,2.7c3.7,1.8,6.9,5,9.8,9.4h0.4c-0.3-5.4-0.4-10.6-0.4-15.8v-21.8c0-1.7,1.4-3.1,3.1-3.1l0,0c1.7,0,3.1,1.4,3.1,3.1
|
||||
v94c0,1.2-1,2.2-2.2,2.2l0,0c-1.1,0-2-0.8-2.2-1.9l-1.3-8.7h-0.5c-5.3,7.9-12.9,11.9-22.7,11.9c-9.6,0-16.9-3-22-8.9
|
||||
c-5.1-6-7.6-14.7-7.6-26.1c0-12,2.5-21.2,7.5-27.5C409,313,416.3,309.8,425.9,309.8z M425.9,315.6c-7.6,0-13.3,2.7-17.1,8
|
||||
c-3.8,5.3-5.7,13.1-5.7,23.2c0,19.7,7.6,29.5,22.9,29.5c7.8,0,13.6-2.3,17.2-6.8c3.7-4.6,5.5-12.1,5.5-22.6v-1.1
|
||||
c0-10.7-1.8-18.5-5.4-23.2C439.8,317.9,433.9,315.6,425.9,315.6z M506.4,381.9c-10.1,0-18-3.1-23.6-9.3c-5.6-6.2-8.5-14.9-8.5-26.1
|
||||
c0-11.1,2.7-19.9,8.2-26.6c5.5-6.7,12.8-10,22-10c8.2,0,14.6,2.9,19.4,8.6c4.7,5.7,7.1,13.5,7.1,23.3v5.1h-50
|
||||
c0.1,9.5,2.3,16.8,6.7,21.8c4.4,5,10.6,7.5,18.7,7.5c4,0,7.4-0.3,10.4-0.8c2.2-0.4,4.8-1.1,7.8-2.2c1.8-0.6,3.6,0.7,3.6,2.6l0,0
|
||||
c0,1.1-0.7,2.1-1.7,2.5c-3.3,1.3-6.3,2.2-9.1,2.8C514,381.6,510.4,381.9,506.4,381.9z M504.5,315.4c-6.7,0-12.1,2.2-16.1,6.6
|
||||
c-4,4.4-6.4,10.8-7.1,19.1h42.9c0-8-1.7-14.3-5.2-18.9C515.5,317.7,510.7,315.4,504.5,315.4z M601.7,380.6c-1.7,0-3.1-1.4-3.1-3.1
|
||||
v-41.9c0-7-1.5-12.1-4.4-15.2c-2.9-3.2-7.5-4.8-13.7-4.8c-8.3,0-14.4,2.1-18.2,6.3c-3.9,4.2-5.8,11-5.8,20.4v35.2
|
||||
c0,1.7-1.4,3.1-3.1,3.1h-0.1c-1.7,0-3.1-1.4-3.1-3.1V314c0-1.6,1.3-2.9,2.9-2.9l0,0c1.4,0,2.6,1.1,2.8,2.5l0.9,7h0.4
|
||||
c4.5-7.2,12.5-10.9,24.1-10.9c15.8,0,23.6,8.5,23.6,25.4v42.3C604.8,379.2,603.4,380.6,601.7,380.6L601.7,380.6z M96.5,280.2
|
||||
L96.5,280.2c-6.3,0-11.4,4.9-11.4,10.9v0.9c0,6,5.1,10.9,11.4,10.9h0c6.3,0,11.4-4.9,11.4-10.9v-0.9
|
||||
C107.9,285.1,102.8,280.2,96.5,280.2z M409.5,7.5c-2.1-2.1-4.7-3.2-7.6-3.2H207.7c-2.9,0-5.5,1.1-7.6,3.2c-2.1,2.1-3.2,4.7-3.2,7.6
|
||||
v129.5c0,9.7,1.9,19.2,5.6,28.7c3.8,9.5,8.4,17.9,14,25.3c5.6,7.4,12.2,14.5,19.9,21.5c7.7,7,14.8,12.8,21.3,17.4
|
||||
c6.5,4.6,13.3,9,20.4,13.1c7.1,4.1,12.1,6.9,15.1,8.3c3,1.5,5.4,2.6,7.2,3.4c1.3,0.7,2.8,1,4.4,1c1.6,0,3-0.3,4.4-1
|
||||
c1.8-0.8,4.2-1.9,7.2-3.4c3-1.5,8-4.2,15.1-8.3c7.1-4.1,13.9-8.5,20.4-13.1c6.5-4.6,13.6-10.4,21.3-17.4c7.7-7,14.3-14.1,19.9-21.5
|
||||
c5.6-7.4,10.2-15.8,14-25.3c3.8-9.5,5.6-19.1,5.6-28.7V15.1C412.7,12.2,411.6,9.7,409.5,7.5z M384.5,145.8
|
||||
c0,46.9-79.6,87.2-79.6,87.2v-201h79.6C384.5,32.1,384.5,98.9,384.5,145.8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
44
Importer/Resources/Styles/Colors.xaml
Normal file
44
Importer/Resources/Styles/Colors.xaml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<Color x:Key="Primary">#175DDC</Color>
|
||||
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||
<Color x:Key="Tertiary">#2CDDE9</Color>
|
||||
<Color x:Key="White">White</Color>
|
||||
<Color x:Key="Black">Black</Color>
|
||||
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||
<Color x:Key="Gray300">#ACACAC</Color>
|
||||
<Color x:Key="Gray400">#919191</Color>
|
||||
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||
<Color x:Key="Gray600">#404040</Color>
|
||||
<Color x:Key="Gray900">#212121</Color>
|
||||
<Color x:Key="Gray950">#141414</Color>
|
||||
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||
|
||||
<Color x:Key="Yellow100Accent">#F7B548</Color>
|
||||
<Color x:Key="Yellow200Accent">#FFD590</Color>
|
||||
<Color x:Key="Yellow300Accent">#FFE5B9</Color>
|
||||
<Color x:Key="Cyan100Accent">#28C2D1</Color>
|
||||
<Color x:Key="Cyan200Accent">#7BDDEF</Color>
|
||||
<Color x:Key="Cyan300Accent">#C3F2F4</Color>
|
||||
<Color x:Key="Blue100Accent">#3E8EED</Color>
|
||||
<Color x:Key="Blue200Accent">#72ACF1</Color>
|
||||
<Color x:Key="Blue300Accent">#A7CBF6</Color>
|
||||
|
||||
</ResourceDictionary>
|
||||
405
Importer/Resources/Styles/Styles.xaml
Normal file
405
Importer/Resources/Styles/Styles.xaml
Normal file
@ -0,0 +1,405 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<Style TargetType="ActivityIndicator">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="IndicatorView">
|
||||
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||
<Setter Property="StrokeThickness" Value="1"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BoxView">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
<Setter Property="Padding" Value="14,10"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="DatePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Editor">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Entry">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray100}, Dark={StaticResource Gray900}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Frame">
|
||||
<Setter Property="HasShadow" Value="False" />
|
||||
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ImageButton">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
<Setter Property="BorderColor" Value="Transparent"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Picker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray100}, Dark={StaticResource Gray900}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RefreshView">
|
||||
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchBar">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchHandler">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shadow">
|
||||
<Setter Property="Radius" Value="15" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Offset" Value="10,10" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Slider">
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SwipeItem">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Switch">
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="On">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Off">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TimePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}" />
|
||||
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="NavigationPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TabbedPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
38
Importer/Services/LastPass/ExportedAccount.cs
Normal file
38
Importer/Services/LastPass/ExportedAccount.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using CsvHelper.Configuration.Attributes;
|
||||
using PasswordManagerAccess.LastPass;
|
||||
|
||||
namespace Bit.Importer.Services.LastPass;
|
||||
|
||||
public class ExportedAccount
|
||||
{
|
||||
public ExportedAccount() { }
|
||||
|
||||
public ExportedAccount(Account account)
|
||||
{
|
||||
Url = account.Url;
|
||||
Username = account.Username;
|
||||
Password = account.Password;
|
||||
// Totp not supported
|
||||
// Extra = account.Notes;
|
||||
Name = account.Name;
|
||||
Grouping = account.Path == "(none)" ? null : account.Path;
|
||||
// Fav = account.Favorite == "1" ? 1 : 0;
|
||||
}
|
||||
|
||||
[Name("url")]
|
||||
public string Url { get; set; }
|
||||
[Name("username")]
|
||||
public string Username { get; set; }
|
||||
[Name("password")]
|
||||
public string Password { get; set; }
|
||||
[Name("totp")]
|
||||
public string Totp { get; set; }
|
||||
[Name("extra")]
|
||||
public string Extra { get; set; }
|
||||
[Name("name")]
|
||||
public string Name { get; set; }
|
||||
[Name("grouping")]
|
||||
public string Grouping { get; set; }
|
||||
[Name("fav")]
|
||||
public int Fav { get; set; }
|
||||
}
|
||||
65
Importer/Services/LastPass/Ui.cs
Normal file
65
Importer/Services/LastPass/Ui.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using PasswordManagerAccess.Common;
|
||||
using PasswordManagerAccess.LastPass.Ui;
|
||||
|
||||
namespace Bit.Importer.Services.LastPass;
|
||||
|
||||
public class Ui : IUi
|
||||
{
|
||||
private readonly MainPage _page;
|
||||
|
||||
public Ui(MainPage page)
|
||||
{
|
||||
_page = page;
|
||||
}
|
||||
|
||||
public OtpResult ProvideGoogleAuthPasscode()
|
||||
{
|
||||
return new OtpResult(PromptCode("Enter your authenticator two-step login code."), false);
|
||||
}
|
||||
|
||||
public OtpResult ProvideMicrosoftAuthPasscode()
|
||||
{
|
||||
return new OtpResult(PromptCode("Enter your authenticator two-step login code."), false);
|
||||
}
|
||||
|
||||
public OtpResult ProvideYubikeyPasscode()
|
||||
{
|
||||
return new OtpResult(PromptCode("Enter your Yubikey code."), false);
|
||||
}
|
||||
|
||||
public OobResult ApproveLastPassAuth()
|
||||
{
|
||||
return OobResult.ContinueWithPasscode(PromptCode("Enter passcode from LastPass authenticator."), false);
|
||||
}
|
||||
|
||||
public OobResult ApproveDuo()
|
||||
{
|
||||
return OobResult.ContinueWithPasscode(PromptCode("Enter passcode from Duo."), false);
|
||||
}
|
||||
|
||||
public DuoChoice ChooseDuoFactor(DuoDevice[] devices)
|
||||
{
|
||||
var task = _page.Dispatcher.DispatchAsync(() =>
|
||||
_page.DisplayActionSheet("Choose a Duo device", "Cancel", null, devices.Select(d => d.Name).ToArray()));
|
||||
var actionSelection = task.GetAwaiter().GetResult();
|
||||
var device = devices.FirstOrDefault(d => d.Name == actionSelection);
|
||||
return new DuoChoice(device, DuoFactor.Passcode, false);
|
||||
}
|
||||
|
||||
public string ProvideDuoPasscode(DuoDevice device)
|
||||
{
|
||||
return PromptCode("Enter your Duo passcode.");
|
||||
}
|
||||
|
||||
public void UpdateDuoStatus(DuoStatus status, string text)
|
||||
{
|
||||
// Not sure what this is for.
|
||||
}
|
||||
|
||||
private string PromptCode(string message)
|
||||
{
|
||||
var task = _page.Dispatcher.DispatchAsync(() =>
|
||||
_page.DisplayPromptAsync("LastPass Two-step Login", message, "Submit"));
|
||||
return task.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
27
bitwarden-importer.sln
Normal file
27
bitwarden-importer.sln
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31611.283
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Importer", "Importer\Importer.csproj", "{46E1189D-8B50-4C55-A443-F4B1BBFF7504}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{46E1189D-8B50-4C55-A443-F4B1BBFF7504}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Loading…
x
Reference in New Issue
Block a user