Merge branch 'feature/NFC' into 'main'

Feature/nfc

See merge request fabinfra/fabaccess/borepin!78
This commit is contained in:
TheJoKlLa 2023-02-27 01:48:10 +00:00
commit 7877d53f0b
44 changed files with 1414 additions and 138 deletions

View File

@ -17,10 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "S22.Sasl", "external\SASL\S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI_Test", "FabAccessAPI_Test\FabAccessAPI_Test.csproj", "{1C85978A-9FC0-4064-8399-FA2455C5EC2A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "external\NFC\NFC\NFC.csproj", "{D53A98E8-48B5-4DCE-A98E-4623EE746E16}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime", "external\capnproto-dotnetcore\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj", "{C587AAC3-50A7-4871-A50D-7880B6F24EF6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borepin_Test", "Borepin_Test\Borepin_Test.csproj", "{A959A406-91A5-4D81-B90D-EF022812D97D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EA0AA4A-A814-45A0-9EA7-E9147CCCCB6A}"
@ -32,6 +28,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Borepin.GTK\Borepin.GTK.csproj", "{61D956D2-5819-4736-BBD8-AD8208DE6A62}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "external\NFC\NFC\NFC.csproj", "{AC068302-655B-46B8-BC8A-971A3D685437}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC.PCSC", "external\NFC\NFC.PCSC\NFC.PCSC.csproj", "{6E2927DD-791F-48FA-96E1-696611FB38EB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime", "external\capnproto-dotnetcore\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj", "{6CC49E97-4F07-43DE-A2AF-50914498A276}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -264,54 +266,6 @@ Global
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|x64.Build.0 = Release|Any CPU
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|x86.ActiveCfg = Release|Any CPU
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|x86.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|ARM.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|iPhone.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|x64.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|x64.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|x86.ActiveCfg = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Debug|x86.Build.0 = Debug|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|Any CPU.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|ARM.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|ARM.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|iPhone.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|iPhone.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|x64.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|x64.Build.0 = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|x86.ActiveCfg = Release|Any CPU
{D53A98E8-48B5-4DCE-A98E-4623EE746E16}.Release|x86.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|ARM.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|ARM.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|iPhone.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|x64.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|x64.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|x86.ActiveCfg = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Debug|x86.Build.0 = Debug|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|Any CPU.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|ARM.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|ARM.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|iPhone.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|iPhone.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|x64.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|x64.Build.0 = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|x86.ActiveCfg = Release|Any CPU
{C587AAC3-50A7-4871-A50D-7880B6F24EF6}.Release|x86.Build.0 = Release|Any CPU
{A959A406-91A5-4D81-B90D-EF022812D97D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A959A406-91A5-4D81-B90D-EF022812D97D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A959A406-91A5-4D81-B90D-EF022812D97D}.Debug|ARM.ActiveCfg = Debug|Any CPU
@ -360,6 +314,78 @@ Global
{61D956D2-5819-4736-BBD8-AD8208DE6A62}.Release|x64.Build.0 = Release|Any CPU
{61D956D2-5819-4736-BBD8-AD8208DE6A62}.Release|x86.ActiveCfg = Release|Any CPU
{61D956D2-5819-4736-BBD8-AD8208DE6A62}.Release|x86.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|ARM.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|ARM.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|iPhone.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|x64.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|x64.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|x86.ActiveCfg = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Debug|x86.Build.0 = Debug|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|Any CPU.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|ARM.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|ARM.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|iPhone.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|iPhone.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|x64.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|x64.Build.0 = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|x86.ActiveCfg = Release|Any CPU
{AC068302-655B-46B8-BC8A-971A3D685437}.Release|x86.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|ARM.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|iPhone.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|x64.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|x64.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|x86.ActiveCfg = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Debug|x86.Build.0 = Debug|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|Any CPU.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|ARM.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|ARM.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|iPhone.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|iPhone.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|x64.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|x64.Build.0 = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|x86.ActiveCfg = Release|Any CPU
{6E2927DD-791F-48FA-96E1-696611FB38EB}.Release|x86.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|ARM.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|iPhone.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|x64.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|x64.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|x86.ActiveCfg = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Debug|x86.Build.0 = Debug|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|Any CPU.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|ARM.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|ARM.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|iPhone.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|iPhone.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|x64.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|x64.Build.0 = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|x86.ActiveCfg = Release|Any CPU
{6CC49E97-4F07-43DE-A2AF-50914498A276}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,12 +1,23 @@

using Android.App;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using AndroidX.AppCompat.App;
namespace Borepin.Droid
{
[Activity(Theme = "@style/MainTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[Activity(Theme = "@style/MainTheme", LaunchMode = LaunchMode.SingleTask, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, Exported = true)]
[IntentFilter(
new[]
{
"android.nfc.action.NDEF_DISCOVERED",
},
Categories = new[]
{
Intent.CategoryDefault
},
DataScheme = "fabaccess"
)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
@ -24,6 +35,15 @@ namespace Borepin.Droid
Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App(new PlatformInitializer()));
}
protected override void OnNewIntent(Intent intent)
{
if(intent.Action == "android.nfc.action.NDEF_DISCOVERED")
{
intent.SetAction(Intent.ActionView);
}
base.OnNewIntent(intent);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{

View File

@ -7,9 +7,9 @@ namespace Borepin.Droid
[Application(Label = "FabAccess", Icon = "@mipmap/ic_launcher")]
public class MainApplication : Application
{
public MainApplication(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
}
}

View File

@ -16,6 +16,7 @@ namespace Borepin.Droid
containerRegistry.Register<ISecretStorageService, SecretStorage>();
containerRegistry.Register<IVersioningService, VersioningService>();
containerRegistry.Register<IBrowserService, BrowserService>();
// TODO containerRegistry.Register<INFCService, NFCService>();
containerRegistry.RegisterSingleton<IAPIService, APIService>();
}

View File

@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="org.fab_infra.fabaccess" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<application android:theme="@style/MainTheme" android:label="FabAccess" android:networkSecurityConfig="@xml/network_security_config"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
</manifest>
<application android:theme="@style/MainTheme" android:label="FabAccess" android:networkSecurityConfig="@xml/network_security_config">
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.BIND_NFC_SERVICE" />
</manifest>

View File

@ -27,6 +27,7 @@ using Android.App;
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.Nfc)]
//#if DEBUG
//[assembly: Application(Debuggable=true)]

View File

@ -187,9 +187,17 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\capnproto-dotnetcore\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj">
<Project>{c587aac3-50a7-4871-a50d-7880b6f24ef6}</Project>
<Project>{6cc49e97-4f07-43de-a2af-50914498a276}</Project>
<Name>Capnp.Net.Runtime</Name>
</ProjectReference>
<ProjectReference Include="..\..\external\NFC\NFC.PCSC\NFC.PCSC.csproj">
<Project>{6e2927dd-791f-48fa-96e1-696611fb38eb}</Project>
<Name>NFC.PCSC</Name>
</ProjectReference>
<ProjectReference Include="..\..\external\NFC\NFC\NFC.csproj">
<Project>{ac068302-655b-46b8-bc8a-971a3d685437}</Project>
<Name>NFC</Name>
</ProjectReference>
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj">
<Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project>
<Name>FabAccessAPI</Name>

View File

@ -54,6 +54,7 @@
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="privateNetworkClientServer"/>
<Capability Name="allJoyn"/>
<uap:Capability Name="sharedUserCertificates"/>
<DeviceCapability Name="proximity"/>
</Capabilities>
</Package>

View File

@ -5,6 +5,8 @@ using Borepin.Service.Storage;
using Borepin.Service.Versioning;
using Borepin.Service;
using Borepin.Service.Browser;
using NFC.PCSC;
using NFC.Interfaces;
namespace Borepin.UWP
{
@ -16,6 +18,7 @@ namespace Borepin.UWP
containerRegistry.Register<ISecretStorageService, SecretStorageService>();
containerRegistry.Register<IVersioningService, VersioningService>();
containerRegistry.Register<IBrowserService, BrowserService>();
containerRegistry.Register<INFCService, NFCService>();
containerRegistry.RegisterSingleton<IAPIService, APIService>();
}

View File

@ -42,5 +42,18 @@
<string>Light</string>
<key>NSCameraUsageDescription</key>
<string>Please allow access to the camera to scan barcodes</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>FabAccess</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fabaccess</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
</dict>
</plist>

View File

@ -16,6 +16,7 @@ namespace Borepin.iOS
containerRegistry.Register<ISecretStorageService, SecretStorageService>();
containerRegistry.Register<IVersioningService, VersioningService>();
containerRegistry.Register<IBrowserService, BrowserService>();
// TODO containerRegistry.Register<INFCService, NFCService>();
containerRegistry.RegisterSingleton<IAPIService, APIService>();
}

View File

@ -13,6 +13,14 @@ using System;
using Borepin.Service.Storage;
using NLog;
using Borepin.Service.ErrorMessage;
using Prism.Navigation.Xaml;
using Prism.Navigation;
using Borepin.Service;
using FabAccessAPI;
using FabAccessAPI.Schema;
using System.Threading.Tasks;
using System.Collections.Generic;
using Prism.Services;
namespace Borepin
{
@ -20,8 +28,8 @@ namespace Borepin
{
public App(IPlatformInitializer platformInitializer) : base(platformInitializer)
{
var config = new NLog.Config.LoggingConfiguration();
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
NLog.Config.LoggingConfiguration config = new NLog.Config.LoggingConfiguration();
NLog.Targets.ConsoleTarget logconsole = new NLog.Targets.ConsoleTarget("logconsole");
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logconsole);
LogManager.Configuration = config;
}
@ -33,6 +41,52 @@ namespace Borepin
await NavigationService.NavigateAsync(new Uri("https://borepin.fab-access.org/StartPage")).ConfigureAwait(false);
}
protected override async void OnAppLinkRequestReceived(Uri uri)
{
IPageDialogService pageDialogService = Container.Resolve<IPageDialogService>();
if (uri.LocalPath.StartsWith("/resource/", StringComparison.OrdinalIgnoreCase))
{
if (Container.IsRegistered<IAPIService>() && Container.IsRegistered<ILoginStorageService>())
{
string resource_id = uri.LocalPath.Remove(0, "/resource/".Length);
IAPIService apiService = Container.Resolve<IAPIService>();
IAPI api = apiService.GetAPI();
if (api.IsConnected)
{
Optional<Machine> optional = await api.Session.MachineSystem.Info.GetMachine(resource_id).ConfigureAwait(false);
if (optional.Just == null)
{
Device.BeginInvokeOnMainThread(async () =>
{
await pageDialogService.DisplayAlertAsync(Borepin.Resources.Text.TextResource.ALERT, Borepin.Resources.Text.TextResource.ALERT_ID, Borepin.Resources.Text.TextResource.OK).ConfigureAwait(false);
});
return;
}
Prism.Navigation.NavigationParameters parameters = new Prism.Navigation.NavigationParameters
{
{ "instance", optional.Just.Id },
};
Device.BeginInvokeOnMainThread(async () =>
{
INavigationResult result = await Container.Resolve<INavigationService>().NavigateAsync("/MainPage/NavigationPage/MachineListPage/MachinePage", parameters).ConfigureAwait(false);
});
}
}
else
{
return;
}
}
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
#region Register Basic Navigation
@ -51,6 +105,7 @@ namespace Borepin
containerRegistry.RegisterForNavigation<UserListPage, UserListPageModel>();
containerRegistry.RegisterForNavigation<UserPage, UserPageModel>();
containerRegistry.RegisterForNavigation<CreateCardPage, CreateCardPageModel>();
containerRegistry.RegisterForNavigation<AddUserPage, AddUserPageModel>();
containerRegistry.RegisterForNavigation<ProfilePage, ProfilePageModel>();
#endregion

View File

@ -111,6 +111,9 @@
<EmbeddedResource Update="Page\AddUserPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Page\CreateCardPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Page\MachinePage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
@ -156,6 +159,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\NFC\NFC\NFC.csproj" />
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,68 @@
using NFC.Helper;
using System;
using System.Globalization;
using System.Security.Cryptography;
namespace Borepin.Model
{
public class CardConfig
{
#region Constructors
public CardConfig()
{
PICCKey = GenerateEmptyKey();
APPKey = GenerateEmptyKey();
}
#endregion
#region Fields
public string UserID;
public byte[] PICCKey;
public byte[] APPKey;
public bool DoFormat;
public byte[] CardToken;
public byte[] MetaInfo;
public byte[] SpaceInfo;
#endregion
#region Mehtods
public string ConvertToString(byte[] array)
{
string data = HexConverter.ConvertToHexString(array);
data = data.ToUpper(CultureInfo.InvariantCulture);
for(int i = 2; i < data.Length; i += 3)
{
data = data.Insert(i, " ");
}
return data;
}
public byte[] ConvertFromString(string data)
{
data = data.Trim();
data = data.Replace(" ", "");
byte[] array = HexConverter.ConvertFromHexString(data);
return array;
}
public byte[] GenerateRandomKey()
{
byte[] key = ByteOperation.GenerateEmptyArray(16);
RNGCryptoServiceProvider cryptoProvider = new RNGCryptoServiceProvider();
cryptoProvider.GetBytes(key);
return key;
}
public byte[] GenerateEmptyKey()
{
return ByteOperation.GenerateEmptyArray(16);
}
#endregion
}
}

View File

@ -0,0 +1,63 @@
using Borepin.Page;
using FabAccessAPI.Schema;
using ImTools;
using NFC.Helper;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Borepin.Model
{
public class DESFireInterfaceDummy : User.ICardDESFireInterface
{
public Task Bind(IReadOnlyList<byte> token, IReadOnlyList<byte> auth_key, CancellationToken cancellationToken_ = default)
{
return Task.CompletedTask;
}
public void Dispose()
{
}
public Task<IReadOnlyList<byte>> GenCardToken(CancellationToken cancellationToken_ = default)
{
List<byte> token = new List<byte>();
token.AddRange(HexConverter.ConvertFromHexString("11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11".Replace(" ", "")));
return Task.FromResult((IReadOnlyList<byte>) token);
}
public Task<IReadOnlyList<byte>> GetMetaInfo(CancellationToken cancellationToken_ = default)
{
List<byte> data = new List<byte>();
data.AddRange(Encoding.ASCII.GetBytes("FABACCESS\0DESFIRE\01.0\0").Append((byte)0x00));
return Task.FromResult((IReadOnlyList<byte>)data);
}
public Task<IReadOnlyList<byte>> GetSpaceInfo(CancellationToken cancellationToken_ = default)
{
List<byte> data = new List<byte>();
data.AddRange(Encoding.ASCII.GetBytes("urn:fabaccess:lab:fabaccess_test").Append((byte)0x00));
return Task.FromResult((IReadOnlyList<byte>)data);
}
public Task<IReadOnlyList<IReadOnlyList<byte>>> GetTokenList(CancellationToken cancellationToken_ = default)
{
List<byte> token = new List<byte>();
token.AddRange(HexConverter.ConvertFromHexString("11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11".Replace(" ", "")));
IReadOnlyList<IReadOnlyList<byte>> list = new List<List<byte>>
{
token
};
return Task.FromResult(list);
}
public Task Unbind(IReadOnlyList<byte> token, CancellationToken cancellationToken_ = default)
{
return Task.CompletedTask;
}
}
}

View File

@ -0,0 +1,116 @@
using Borepin.Service.ErrorMessage;
using NFC.Cards.NXP_MIFARE_DESFire;
using NFC.Cards.NXP_MIFARE_DESFire.Enums;
using NFC.Helper;
using NFC.Helper.Crypto;
using NFC.Interfaces;
using System;
using System.Text;
using ZXing.Aztec.Internal;
namespace Borepin.Model
{
public class FabFireCard
{
#region Private Fields
readonly INFCService _NFCService;
readonly IErrorMessageService _ErrorMessageService;
#endregion
#region Constructors
public FabFireCard(INFCService nfcService, IErrorMessageService errorMessageService)
{
_NFCService = nfcService;
_ErrorMessageService = errorMessageService;
}
#endregion
#region Methods
/// <summary>
/// Format Card
/// </summary>
/// <param name="readerID"></param>
/// <param name="cardConfig"></param>
public void FormatCard(string readerID, CardConfig cardConfig)
{
CipherKey PICCKey = new CipherKey(cardConfig.PICCKey, CipherType.TDES, 0x00);
_NFCService.Connect(readerID);
NXP_MIFARE_DESFire card = new NXP_MIFARE_DESFire(_NFCService);
card.SelectApplication(0x000000);
card.AuthenticateISO_DES(0x00, PICCKey._Key);
card.Format();
_NFCService.Disconnect();
}
/// <summary>
/// Create DESFire Card for V1.0
/// </summary>
/// <param name="readerID"></param>
/// <param name="cardConfig"></param>
/// <returns>Key #1 for authentication </returns>
public byte[] CreateCard(string readerID, CardConfig cardConfig)
{
CipherKey PICCKey = new CipherKey(cardConfig.PICCKey, CipherType.TDES, 0x00);
CipherKey MasterKey = new CipherKey(cardConfig.APPKey, CipherType.AES, 0x10);
CipherKey AuthKey = new CipherKey(cardConfig.GenerateRandomKey(), CipherType.AES, 0x10);
UInt32 AID = 0x464142;
CipherKey _Default_DESKey = new CipherKey(CipherType.TDES);
CipherKey _Default_AESKey = new CipherKey(CipherType.AES);
_NFCService.Connect(readerID);
NXP_MIFARE_DESFire card = new NXP_MIFARE_DESFire(_NFCService);
if (cardConfig.DoFormat)
{
card.AuthenticateISO_DES(0x00, _Default_DESKey._Key);
}
else
{
card.AuthenticateISO_DES(0x00, PICCKey._Key);
}
byte keySetting1 = card.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE);
byte keySetting2 = card.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x02);
card.CreateApplication(AID, keySetting1, keySetting2);
card.SelectApplication(AID);
card.AuthenticateISO_AES(0x00, _Default_AESKey._Key);
card.ChangeKey_AES(0x00, MasterKey._Key, MasterKey._KeyVersion);
card.AuthenticateISO_AES(0x00, MasterKey._Key);
card.ChangeOtherKey_AES(0x01, AuthKey._Key, _Default_AESKey._Key, AuthKey._KeyVersion);
UInt16 accessRights = card.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00);
card.CreateFile_Standard(0x01, FileCommunication.PLAIN, accessRights, (uint)cardConfig.MetaInfo.Length);
card.CreateFile_Standard(0x02, FileCommunication.PLAIN, accessRights, (uint)cardConfig.SpaceInfo.Length);
card.CreateFile_Standard(0x03, FileCommunication.PLAIN, accessRights, (uint)47);// TODO (uint)cardConfig.CardToken.Length);
card.WriteData(0x01, 0x00, cardConfig.MetaInfo);
card.WriteData(0x02, 0x00, cardConfig.SpaceInfo);
card.WriteData(0x03, 0x00, _TODOFixDataFileSize(cardConfig.CardToken));
_NFCService.Disconnect();
return AuthKey._Key;
}
/// <summary>
/// TODO implement GetFileInfo in DESFire
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private byte[] _TODOFixDataFileSize(byte[] data)
{
byte[] array = ByteOperation.GenerateEmptyArray(47);
data.CopyTo(array, 0);
return array;
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
namespace Borepin.Model
{
public class KeyScan
{
public KeyScan(CardConfig cardConfig, KeyTypes keyType)
{
CardConfig = cardConfig;
KeyType = keyType;
}
public CardConfig CardConfig;
public KeyTypes KeyType;
}
}

View File

@ -0,0 +1,9 @@
namespace Borepin.Model
{
public enum KeyTypes
{
NONE,
PICC,
APP
};
}

View File

@ -21,6 +21,11 @@ namespace Borepin.Model
#region Methods
public async Task LoadData()
{
if(_Machine== null)
{
return;
}
//ID = _Machine.Id;
//Space = new SpaceVisualize(_Machine.Space);
Name = _Machine.Name;
@ -75,6 +80,7 @@ namespace Borepin.Model
CanManage = !((ManageInterface_Proxy)_Machine.Manage).IsNull;
CanAdmin = !((AdminInterface_Proxy)_Machine.Admin).IsNull;
CanNotUseByPermission = State == MachineState.free && !CanUse;
IsLock = !((ProdInterface_Proxy)_Machine.Prodable).IsNull;
}
#endregion
@ -197,6 +203,13 @@ namespace Borepin.Model
get => _CanNotUseByPermission;
set => SetProperty(ref _CanNotUseByPermission, value);
}
private bool _IsLock;
public bool IsLock
{
get => _IsLock;
set => SetProperty(ref _IsLock, value);
}
#endregion
}
}

View File

@ -20,6 +20,11 @@ namespace Borepin.Model
#region LoadData
public Task LoadData()
{
if(_User == null)
{
return Task.CompletedTask;
}
//ID = _User.Id;
Username = _User.Username;
//Space = new SpaceVisualize(_User.Space);

View File

@ -13,7 +13,8 @@
<ContentPage.Content>
<StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_TryConnection}" IsVisible="{Binding TestConnection}" Style="{StaticResource Style_Label_Text_Center}"/>
<ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.USERNAME}" Style="{StaticResource Style_Label_Property_Title}"></Label>

View File

@ -13,7 +13,7 @@
<ContentPage.Content>
<StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_ChooseAuthTypePage_SignIn}" Style="{StaticResource Style_Label_Property_Title}"></Label>

View File

@ -12,21 +12,24 @@
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<StackLayout>
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_TryConnection}" IsVisible="{Binding TestConnection}" Style="{StaticResource Style_Label_Text_Center}"/>
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}"/>
</StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.HOST}" Style="{StaticResource Style_Label_Property_Title}"></Label>
<Entry Text="{Binding Host}" Keyboard="Url" IsSpellCheckEnabled="false"/>
<Entry Text="{Binding Host}" Placeholder="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_Placeholder}" PlaceholderColor="{StaticResource SecondColor}" Keyboard="Url" IsSpellCheckEnabled="false"/>
<Button Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_Connect}" Command="{Binding ConnectToServerCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button Text="{x:Static resource_text:TextResource.SCANQR}" Command="{Binding ScanCodeCommand}" Style="{StaticResource Style_Button_Primary}">
<Button.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean"
iOS="true"
Android="true"/>
<OnPlatform x:TypeArguments="x:Boolean">
<On Platform="iOS" Value="True" />
<On Platform="Android" Value="True" />
<On Platform="UWP" Value="False" />
</OnPlatform>
</Button.IsVisible>
</Button>
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_Info}"></Label>
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_Info}" Margin="0, 20, 0, 0"></Label>
</StackLayout>
</StackLayout>
</ContentPage.Content>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Borepin.Page.CreateCardPage"
xmlns:converters="clr-namespace:Borepin.Converter"
xmlns:resource_text="clr-namespace:Borepin.Resources.Text"
xmlns:views="clr-namespace:Borepin.View"
Title="Create Card">
<NavigationPage.TitleView>
<Button Text="Refresh" HorizontalOptions="End" BackgroundColor="{StaticResource SecondColor}" TextColor="{StaticResource FirstColor}" Command="{Binding RefreshCommand}"/>
</NavigationPage.TitleView>
<ContentPage.Resources>
<ResourceDictionary>
<converters:AllTrueBoolConverter x:Key="AllTrueBoolConverter"/>
<converters:InvertBoolConverter x:Key="InvertBoolConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="20">
<views:ConnectionStateView/>
<StackLayout>
<StackLayout.IsVisible>
<MultiBinding Converter="{StaticResource AllTrueBoolConverter}">
<Binding Path="IsBusy" Converter="{StaticResource InvertBoolConverter}"/>
<Binding Path="IsConnected" />
</MultiBinding>
</StackLayout.IsVisible>
<Label Text="NFC Reader" Style="{StaticResource Style_Label_Property_Title}"></Label>
<Picker ItemsSource="{Binding ReaderIDs}" SelectedItem="{Binding ReaderID}"></Picker>
<Label Text="PICC Key" Style="{StaticResource Style_Label_Property_Title}"></Label>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Entry Grid.Column="0" Text="{Binding PICCKey}" IsSpellCheckEnabled="false"/>
<Button Grid.Column="2" Text="Scan QR-Code" Command="{Binding ScanPICCKeyCommand}" Style="{StaticResource Style_Button_Primary}" IsVisible="False"/>
</Grid>
<Label Text="Application Key" Style="{StaticResource Style_Label_Property_Title}"></Label>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Entry Grid.Column="0" Text="{Binding APPKey}" IsSpellCheckEnabled="false"/>
<Button Grid.Column="1" Text="Random" Command="{Binding RandomAPPKeyCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button Grid.Column="2" Text="Scan QR-Code" Command="{Binding ScanAPPKeyCommand}" Style="{StaticResource Style_Button_Primary}" IsVisible="False"/>
</Grid>
<StackLayout Orientation="Horizontal">
<CheckBox IsChecked="{Binding FormatCard}"/>
<Label Text="Format Card" VerticalOptions="Center"/>
</StackLayout>
<Button Text="Create Card" Command="{Binding CreateCardCommand}" Style="{StaticResource Style_Button_Primary}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Borepin.Page
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CreateCardPage : ContentPage
{
public CreateCardPage()
{
InitializeComponent();
}
}
}

View File

@ -29,12 +29,14 @@
</MultiBinding>
</StackLayout.IsVisible>
<Button Text="{x:Static resource_text:TextResource.SCANQR}" Command="{Binding ScanCodeCommand}" Style="{StaticResource Style_Button_Primary}">
<Button.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean"
iOS="True"
Android="True"/>
</Button.IsVisible>
</Button>
<Button.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean">
<On Platform="iOS" Value="True" />
<On Platform="Android" Value="True" />
<On Platform="UWP" Value="False" />
</OnPlatform>
</Button.IsVisible>
</Button>
<ListView ItemsSource="{Binding MachineListItemViewModel_List}" SelectionMode="None" SeparatorColor="Transparent" IsGroupingEnabled="True" GroupDisplayBinding="{Binding Category}">
<ListView.GroupHeaderTemplate>
<DataTemplate>

View File

@ -43,15 +43,23 @@
<Label Text="{Binding MachineItem.CurrentUser.Username}" Style="{StaticResource Style_Label_Property_Text}"/>
</StackLayout>
<Button Text="{x:Static resource_text:TextResource.MachinePage_Use}" IsVisible="{Binding MachineItem.CanUse}" Command="{Binding UseMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Label Text="{x:Static resource_text:TextResource.MachinePage_CanNotUseByPermission}" IsVisible="{Binding MachineItem.CanNotUseByPermission}" Style="{StaticResource Style_Label_Text_Center}"/>
<Button Text="{x:Static resource_text:TextResource.MachinePage_GiveBack}" IsVisible="{Binding MachineItem.CanInUse}" Command="{Binding GiveBackMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button VerticalOptions="End" Text="{x:Static resource_text:TextResource.MachinePage_OpenWiki}" IsVisible="{Binding MachineItem.Wiki, Converter={StaticResource IsNotNullBoolConverter}}" Command="{Binding OpenWikiCommand}" Style="{StaticResource Style_Button_Primary}"/>
<StackLayout Grid.Row="2" VerticalOptions="End" IsVisible="{Binding MachineItem.CanManage}">
<StackLayout>
<Button Text="{x:Static resource_text:TextResource.MachinePage_Use}" IsVisible="{Binding MachineItem.CanUse}" Command="{Binding UseMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Label Text="{x:Static resource_text:TextResource.MachinePage_CanNotUseByPermission}" IsVisible="{Binding MachineItem.CanNotUseByPermission}" Style="{StaticResource Style_Label_Text_Center}" TextColor="{StaticResource FourthColor}"/>
<Button Text="{x:Static resource_text:TextResource.MachinePage_GiveBack}" IsVisible="{Binding MachineItem.CanInUse}" Command="{Binding GiveBackMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
</StackLayout>
<StackLayout Margin="0,10,0,0" IsVisible="{Binding MachineItem.IsLock}">
<Button Text="{x:Static resource_text:TextResource.MachinePage_Unlock}" Command="{Binding UnlockLockCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button Text="{x:Static resource_text:TextResource.MachinePage_Identify}" Command="{Binding IdentifyLockCommand}" Style="{StaticResource Style_Button_Primary}"/>
</StackLayout>
<Button VerticalOptions="End" Text="{x:Static resource_text:TextResource.MachinePage_OpenWiki}" IsVisible="{Binding MachineItem.Wiki, Converter={StaticResource IsNotNullBoolConverter}}" Command="{Binding OpenWikiCommand}" Margin="0,10,0,0" Style="{StaticResource Style_Button_Primary}"/>
<StackLayout Grid.Row="2" VerticalOptions="End" IsVisible="{Binding MachineItem.CanManage}" Margin="0,50,0,0">
<Label Text="{x:Static resource_text:TextResource.MachinePage_ManageMachine}" Style="{StaticResource Style_Label_Property_Title}"/>
<StackLayout Margin="10, 0, 0, 20" Orientation="Horizontal" IsVisible="{Binding MachineItem.LastUser, Converter={StaticResource IsNotNullBoolConverter}}">
<StackLayout Orientation="Horizontal" IsVisible="{Binding MachineItem.LastUser, Converter={StaticResource IsNotNullBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.MachinePage_LastUser}" Style="{StaticResource Style_Label_Property_Title}"/>
<Label Text="{Binding MachineItem.LastUser.Username}" Style="{StaticResource Style_Label_Property_Text}" Margin="10, 0, 0, 0"/>
<Label Text="{Binding MachineItem.LastUser.Username}" Style="{StaticResource Style_Label_Property_Text}"/>
</StackLayout>
<Button Text="{x:Static resource_text:TextResource.MachinePage_ForceFree}" Command="{Binding ForceFreeMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button Text="{x:Static resource_text:TextResource.MachinePage_ForceBlock}" Command="{Binding ForceBlockMachineCommand}" Style="{StaticResource Style_Button_Admin}"/>

View File

@ -15,7 +15,7 @@
<ContentPage.Content>
<StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand">
<Label Text="{x:Static resource_text:TextResource.ServerListPage_ActiveConnection}" IsVisible="{Binding HasActiveConnection}"/>

View File

@ -13,7 +13,8 @@
<ContentPage.Content>
<StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_SelectServerPage_TryConnection}" IsVisible="{Binding TestConnection}" Style="{StaticResource Style_Label_Text_Center}"/>
<ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout>
<Grid IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
@ -23,8 +24,11 @@
<StackLayout Grid.Row="0">
<Label Text="{Binding DisplayAddress}" Style="{StaticResource LabelStyle_Title}"/>
<Label Text="{Binding Connection_Item.Username}" Style="{StaticResource Style_Label_Text_Center}"/>
<Button IsVisible="{Binding InstanceIsDefaultConnection, Converter={StaticResource InvertBoolConverter}}" Text="{x:Static resource_text:TextResource.ServerPage_SetDefault}" Margin="0,10,0,0" Command="{Binding SetDefaultCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Label IsVisible="{Binding InstanceIsDefaultConnection}" Text="{x:Static resource_text:TextResource.ServerPage_IsDefault}" Style="{StaticResource Style_Label_Text_Center}"/>
<Label IsVisible="{Binding InstanceIsDefaultConnection}" Text="{x:Static resource_text:TextResource.ServerPage_IsDefault}" Style="{StaticResource Style_Label_Text_Center}" TextColor="{StaticResource FourthColor}"/>
<Label IsVisible="{Binding InstanceIsDefaultConnection,Converter={StaticResource InvertBoolConverter}}" Text="{x:Static resource_text:TextResource.ServerPage_DefaultText}" Style="{StaticResource Style_Label_Text_Center}" TextColor="{StaticResource FourthColor}"/>
<Button IsVisible="{Binding InstanceIsActiveConnection, Converter={StaticResource InvertBoolConverter}}" Text="{x:Static resource_text:TextResource.ServerPage_Connect}" Margin="0,10,0,0" Command="{Binding ConnectCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button IsVisible="{Binding InstanceIsActiveConnection}" Text="{x:Static resource_text:TextResource.ServerPage_Disconnect}" Margin="0,10,0,0" Command="{Binding DisconnectCommand}" Style="{StaticResource Style_Button_Admin}"/>
</StackLayout>

View File

@ -27,7 +27,7 @@
</MultiBinding>
</StackLayout.IsVisible>
<Button Text="{x:Static resource_text:TextResource.UserListPage_AddUser}" Command="{Binding AddUserCommand}" Style="{StaticResource Style_Button_Primary}"/>
<SearchBar Text="{Binding SearchUsername}" SearchCommand="{Binding SearchUserCommand}">
<SearchBar Text="{Binding SearchUsername}" SearchCommand="{Binding SearchUserCommand}" Placeholder="{x:Static resource_text:TextResource.UserListPage_Search}" PlaceholderColor="{StaticResource SecondColor}">
<SearchBar.Behaviors>
<prism:EventToCommandBehavior EventName="TextChanged" Command="{Binding SearchUserCommand}"/>
</SearchBar.Behaviors>

View File

@ -22,7 +22,7 @@
<StackLayout.IsVisible>
<MultiBinding Converter="{StaticResource AllTrueBoolConverter}">
<Binding Path="IsBusy" Converter="{StaticResource InvertBoolConverter}"/>
<Binding Path="IsConnected" />
<Binding Path="IsConnected"/>
</MultiBinding>
</StackLayout.IsVisible>
<Label Text="{Binding UserItem.Username}" Style="{StaticResource LabelStyle_Title}"/>
@ -40,7 +40,21 @@
<Entry Placeholder="{x:Static resource_text:TextResource.UserPage_NewPassword}" Text="{Binding NewPassword}"/>
<Button Text="{x:Static resource_text:TextResource.UserPage_UpdatePassword}" Command="{Binding UpdatePasswordCommand}" Style="{StaticResource Style_Button_Primary}"/>
</StackLayout>
<Button Grid.Row="1" Text="{x:Static resource_text:TextResource.DELETE}" Command="{Binding DeleteCommand}" Style="{StaticResource Style_Button_Admin}" VerticalOptions="End"/>
<StackLayout IsVisible="{Binding CanCreateCard}">
<StackLayout >
<StackLayout.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean">
<On Platform="iOS" Value="False" />
<On Platform="Android" Value="False" />
<On Platform="UWP" Value="True" />
</OnPlatform>
</StackLayout.IsVisible>
<Button Text="{x:Static resource_text:TextResource.UserPage_CreateCard}" Command="{Binding CreateCardCommand}" IsVisible="{Binding HasCardBinded, Converter={StaticResource InvertBoolConverter}}" Style="{StaticResource Style_Button_Primary}"/>
<Button Text="{x:Static resource_text:TextResource.UserPage_UnbindCard}" Command="{Binding UnbindCardCommand}" IsVisible="{Binding HasCardBinded}" Style="{StaticResource Style_Button_Admin}"/>
</StackLayout>
</StackLayout>
<Button Text="{x:Static resource_text:TextResource.DELETE}" Command="{Binding DeleteCommand}" Style="{StaticResource Style_Button_Admin}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>

View File

@ -71,6 +71,13 @@ namespace Borepin.PageModel.AddServerProcess
get => _Password;
set => SetProperty(ref _Password, value);
}
private bool _TestConnection;
public bool TestConnection
{
get => _TestConnection;
set => SetProperty(ref _TestConnection, value);
}
#endregion
#region Commands
@ -83,7 +90,8 @@ namespace Borepin.PageModel.AddServerProcess
public async Task AuthenticateCommandExecute()
{
IsBusy = true;
if(Username == null || Username == String.Empty || Password == null || Password == String.Empty)
TestConnection = true;
if (Username == null || Username == String.Empty || Password == null || Password == String.Empty)
{
IsBusy = false;
return;
@ -119,7 +127,9 @@ namespace Borepin.PageModel.AddServerProcess
catch (Exception exception)
{
_ErrorMessageService.DisplayConnectFailedMessage(exception);
IsBusy = false;
TestConnection = false;
return;
}
@ -134,6 +144,9 @@ namespace Borepin.PageModel.AddServerProcess
Log.Fatal(result.Exception, "Navigating failed");
}
});
IsBusy = false;
TestConnection = false;
}
#endregion
}

View File

@ -1,7 +1,6 @@
using Borepin.Base;
using Borepin.Service.ErrorMessage;
using FabAccessAPI;
using FabAccessAPI.Exceptions;
using Prism.Commands;
using Prism.Navigation;
using Prism.Services;
@ -28,6 +27,8 @@ namespace Borepin.PageModel.AddServerProcess
ConnectToServerCommand = new DelegateCommand(async () => await ConnectToServerExecute().ConfigureAwait(false));
DetectLocalServerCommand = new DelegateCommand(DetectHostCommandExecute);
ScanCodeCommand = new DelegateCommand(ScanCodeCommandExecute);
TestConnection = false;
}
#endregion
@ -37,7 +38,7 @@ namespace Borepin.PageModel.AddServerProcess
if(instance is ConnectionData)
{
_ConnectionData = instance as ConnectionData;
Host = _ConnectionData.Host.ToString();
Host = _ConnectionData.Host.Host + ":" + _ConnectionData.Host.Port;
}
return Task.CompletedTask;
@ -66,6 +67,13 @@ namespace Borepin.PageModel.AddServerProcess
get => _Host;
set => SetProperty(ref _Host, value);
}
private bool _TestConnection;
public bool TestConnection
{
get => _TestConnection;
set => SetProperty(ref _TestConnection, value);
}
#endregion
#region Commands
@ -86,6 +94,7 @@ namespace Borepin.PageModel.AddServerProcess
try
{
TestConnection = true;
string server_address = "";
if(Regex.IsMatch(Host, "([a-zA-Z]{2,20}):\\/\\/", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(1)))
{
@ -101,6 +110,7 @@ namespace Borepin.PageModel.AddServerProcess
{
builder.Port = 59661;
}
builder.Scheme = "fabaccess";
_ConnectionData = new ConnectionData()
{
@ -113,6 +123,7 @@ namespace Borepin.PageModel.AddServerProcess
{
await _PageDialogService.DisplayAlertAsync(Resources.Text.TextResource.ALERT_ConnectionFailed, Resources.Text.TextResource.ALERT_AddressInvalid, Resources.Text.TextResource.OK).ConfigureAwait(false);
TestConnection = false;
IsBusy = false;
});
@ -127,6 +138,8 @@ namespace Borepin.PageModel.AddServerProcess
catch(Exception exception)
{
_ErrorMessageService.DisplayConnectFailedMessage(exception);
TestConnection = false;
IsBusy = false;
return;
}
@ -139,6 +152,9 @@ namespace Borepin.PageModel.AddServerProcess
Log.Fatal(result.Exception, "Navigating failed");
}
});
TestConnection = false;
IsBusy = false;
}
private ICommand _ScanCodeCommand;

View File

@ -0,0 +1,441 @@
using Borepin.Base;
using Prism.Commands;
using Prism.Navigation;
using System.Windows.Input;
using FabAccessAPI.Schema;
using Prism.Services;
using Borepin.Service;
using System.Threading.Tasks;
using Borepin.Base.Exceptions;
using NFC.Interfaces;
using System.Collections.Generic;
using Borepin.Model;
using Xamarin.Forms;
using System;
using Borepin.Service.ErrorMessage;
using System.Linq;
namespace Borepin.PageModel
{
public class CreateCardPageModel : ConnectionModelBase
{
#region Private Fields
private CardConfig _CardConfig;
private User _User;
private INFCService _NFCService;
private IErrorMessageService _ErrorMessageService;
private KeyTypes _ScanKeyType = KeyTypes.NONE;
private KeyTypes _ScanedKeyType = KeyTypes.NONE;
#endregion
#region Contructors
public CreateCardPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService, INFCService nfcService, IErrorMessageService errorMessageService) : base(navigationService, pageDialogService, apiService)
{
_NFCService = nfcService;
_ErrorMessageService = errorMessageService;
_CardConfig= new CardConfig();
CreateCardCommand = new DelegateCommand(CreateCardCommandExecute);
ScanPICCKeyCommand = new DelegateCommand(ScanPICCKeyCommandExecute);
ScanAPPKeyCommand = new DelegateCommand(ScanAPPKeyCommandExecute);
RandomAPPKeyCommand = new DelegateCommand(RandomAPPKeyCommandExecute);
RefreshCommand = new DelegateCommand(async () => await RefreshCommandExecute().ConfigureAwait(true));
}
#endregion
#region Data
public override Task LoadInstance(object instance)
{
if (instance is string)
{
_CardConfig.UserID = instance as string;
}
else if (instance is CardConfig)
{
_CardConfig = instance as CardConfig;
}
else if (instance is KeyScan)
{
KeyScan keyScan = instance as KeyScan;
_CardConfig = keyScan.CardConfig;
_ScanedKeyType = keyScan.KeyType;
_ScanKeyType = KeyTypes.NONE;
}
else
{
throw new InstanceIncorrectException();
}
return Task.CompletedTask;
}
public override Task LoadFromParameters(INavigationParameters parameters)
{
if (parameters.ContainsKey("result") && string.Equals((string)parameters["result"], "scanned", StringComparison.Ordinal) && parameters.ContainsKey("value"))
{
switch(_ScanedKeyType)
{
case (KeyTypes.PICC):
try
{
_CardConfig.PICCKey = _CardConfig.ConvertFromString(PICCKey);
}
catch
{
_CardConfig.PICCKey = _CardConfig.GenerateEmptyKey();
}
_CardConfig.PICCKey = _CardConfig.ConvertFromString((string)parameters["value"]);
PICCKey = _CardConfig.ConvertToString(_CardConfig.PICCKey);
break;
case (KeyTypes.APP):
try
{
_CardConfig.APPKey = _CardConfig.ConvertFromString((string)parameters["value"]);
}
catch
{
_CardConfig.APPKey = _CardConfig.GenerateEmptyKey();
}
APPKey = _CardConfig.ConvertToString(_CardConfig.APPKey);
break;
}
}
return Task.CompletedTask;
}
public override async Task LoadAPIData()
{
_User = (await _API.Session.UserSystem.Search.GetUserByName(_CardConfig.UserID).ConfigureAwait(false)).Just;
ReaderIDs = await Task.Run(() =>
{
return _NFCService.GetReaderIDs();
}).ConfigureAwait(false);
// Delay to sync with XAML Picker Item Source
await Task.Delay(100).ConfigureAwait(false);
if (ReaderIDs.Count > 0)
{
ReaderID = ReaderIDs[0];
}
PICCKey = _CardConfig.ConvertToString(_CardConfig.PICCKey);
APPKey = _CardConfig.ConvertToString(_CardConfig.APPKey);
FormatCard = _CardConfig.DoFormat;
}
public override Task<object> CreateInstance()
{
try
{
_CardConfig.PICCKey = _CardConfig.ConvertFromString(PICCKey);
}
catch
{
_CardConfig.PICCKey = _CardConfig.GenerateEmptyKey();
}
try
{
_CardConfig.APPKey = _CardConfig.ConvertFromString(APPKey);
}
catch
{
_CardConfig.APPKey = _CardConfig.GenerateEmptyKey();
}
_CardConfig.DoFormat = FormatCard;
switch(_ScanKeyType)
{
case (KeyTypes.PICC):
return Task.FromResult<object>(new KeyScan(_CardConfig, KeyTypes.PICC));
case (KeyTypes.APP):
return Task.FromResult<object>(new KeyScan(_CardConfig, KeyTypes.APP));
case (KeyTypes.NONE):
default:
return Task.FromResult<object>(_CardConfig);
}
}
#endregion
#region Fields
private IList<string> _ReaderIDs;
public IList<string> ReaderIDs
{
get => _ReaderIDs;
set => SetProperty(ref _ReaderIDs, value);
}
private string _ReaderID;
public string ReaderID
{
get => _ReaderID;
set => SetProperty(ref _ReaderID, value);
}
private string _PICCKey;
public string PICCKey
{
get => _PICCKey;
set => SetProperty(ref _PICCKey, value);
}
private string _APPKey;
public string APPKey
{
get => _APPKey;
set => SetProperty(ref _APPKey, value);
}
private bool _FormatCard;
public bool FormatCard
{
get => _FormatCard;
set => SetProperty(ref _FormatCard, value);
}
#endregion
#region Commands
private ICommand _RefreshCommand;
public ICommand RefreshCommand
{
get => _RefreshCommand;
set => SetProperty(ref _RefreshCommand, value);
}
public async Task RefreshCommandExecute()
{
if (_API.IsConnected)
{
try
{
await LoadAPIData().ConfigureAwait(true);
}
catch (System.Exception)
{
// TODO
}
}
}
private ICommand _CreateCardCommand;
public ICommand CreateCardCommand
{
get => _CreateCardCommand;
set => SetProperty(ref _CreateCardCommand, value);
}
public async void CreateCardCommandExecute()
{
IsBusy = true;
if(ReaderID == null)
{
Device.BeginInvokeOnMainThread(async () =>
{
await _PageDialogService.DisplayAlertAsync("NFC Error", "No Card Reader selected", Resources.Text.TextResource.OK).ConfigureAwait(false);
IsBusy = false;
});
return;
}
try
{
_CardConfig.PICCKey = _CardConfig.ConvertFromString(PICCKey);
}
catch
{
Device.BeginInvokeOnMainThread(async () =>
{
await _PageDialogService.DisplayAlertAsync("NFC Error", "PICC Key invalid", Resources.Text.TextResource.OK).ConfigureAwait(false);
IsBusy = false;
});
return;
}
try
{
_CardConfig.APPKey = _CardConfig.ConvertFromString(APPKey);
}
catch
{
Device.BeginInvokeOnMainThread(async () =>
{
await _PageDialogService.DisplayAlertAsync("NFC Error", "APP Key invalid", Resources.Text.TextResource.OK).ConfigureAwait(false);
IsBusy = false;
});
return;
}
_CardConfig.DoFormat = FormatCard;
_CardConfig.CardToken = (await _User.CardDESFireEV2.GenCardToken().ConfigureAwait(false)).ToArray();
_CardConfig.SpaceInfo = (await _User.CardDESFireEV2.GetSpaceInfo().ConfigureAwait(false)).ToArray();
_CardConfig.MetaInfo = (await _User.CardDESFireEV2.GetMetaInfo().ConfigureAwait(false)).ToArray();
FabFireCard fabFireCard = new FabFireCard(_NFCService, _ErrorMessageService);
try
{
if(FormatCard)
{
fabFireCard.FormatCard(ReaderID, _CardConfig);
}
}
catch(Exception exception)
{
Device.BeginInvokeOnMainThread(async () =>
{
await _PageDialogService.DisplayAlertAsync("NFC Error", "Format failed", Resources.Text.TextResource.OK).ConfigureAwait(false);
IsBusy = false;
});
_NFCService.Disconnect();
return;
}
try
{
byte[] key = fabFireCard.CreateCard(ReaderID, _CardConfig);
await _User.CardDESFireEV2.Bind(_CardConfig.CardToken, new List<byte>(key)).ConfigureAwait(false);
}
catch(Exception excpetion)
{
Device.BeginInvokeOnMainThread(async () =>
{
await _PageDialogService.DisplayAlertAsync("NFC Error", "Card Creation failed", Resources.Text.TextResource.OK).ConfigureAwait(false);
IsBusy = false;
});
_NFCService.Disconnect();
return;
}
Device.BeginInvokeOnMainThread(async () =>
{
INavigationResult result = await _NavigationService.GoBackAsync().ConfigureAwait(false);
});
IsBusy = false;
}
#region PICCKey
private ICommand _ScanPICCKeyCommand;
public ICommand ScanPICCKeyCommand
{
get => _ScanPICCKeyCommand;
set => SetProperty(ref _ScanPICCKeyCommand, value);
}
public void ScanPICCKeyCommandExecute()
{
_ScanKeyType = KeyTypes.PICC;
Device.BeginInvokeOnMainThread(async () =>
{
INavigationResult result = await _NavigationService.NavigateAsync("ScanPage").ConfigureAwait(false);
if (result.Exception != null)
{
Log.Fatal(result.Exception, "Navigating failed");
}
});
}
private ICommand _RandomPICCKeyCommand;
public ICommand RandomPICCKeyCommand
{
get => _RandomPICCKeyCommand;
set => SetProperty(ref _RandomPICCKeyCommand, value);
}
public void RandomPICCKeyCommandExecute()
{
_CardConfig.PICCKey = _CardConfig.GenerateRandomKey();
PICCKey = _CardConfig.ConvertToString(_CardConfig.PICCKey);
}
private ICommand _ExportPICCKeyCommand;
public ICommand ExportPICCKeyCommand
{
get => _ExportPICCKeyCommand;
set => SetProperty(ref _ExportPICCKeyCommand, value);
}
public async void ExportPICCKeyCommandExecute()
{
IsBusy = true;
await Task.Delay(1000).ConfigureAwait(false);
IsBusy = false;
}
#endregion
#region APPKey
private ICommand _ScanAPPKeyCommand;
public ICommand ScanAPPKeyCommand
{
get => _ScanAPPKeyCommand;
set => SetProperty(ref _ScanAPPKeyCommand, value);
}
public void ScanAPPKeyCommandExecute()
{
_ScanKeyType = KeyTypes.APP;
Device.BeginInvokeOnMainThread(async () =>
{
INavigationResult result = await _NavigationService.NavigateAsync("ScanPage").ConfigureAwait(false);
if (result.Exception != null)
{
Log.Fatal(result.Exception, "Navigating failed");
}
});
}
private ICommand _RandomAPPKeyCommand;
public ICommand RandomAPPKeyCommand
{
get => _RandomAPPKeyCommand;
set => SetProperty(ref _RandomAPPKeyCommand, value);
}
public void RandomAPPKeyCommandExecute()
{
_CardConfig.APPKey = _CardConfig.GenerateRandomKey();
APPKey = _CardConfig.ConvertToString(_CardConfig.APPKey);
}
private ICommand _ExportAPPKeyCommand;
public ICommand ExportAPPKeyCommand
{
get => _ExportAPPKeyCommand;
set => SetProperty(ref _ExportAPPKeyCommand, value);
}
public async void ExportAPPKeyCommandExecute()
{
IsBusy = true;
await Task.Delay(1000).ConfigureAwait(false);
IsBusy = false;
}
#endregion
#endregion
}
}

View File

@ -11,6 +11,7 @@ using Borepin.Base.Exceptions;
using Capnp.Rpc;
using System;
using Borepin.Service.Browser;
using System.Text;
namespace Borepin.PageModel
{
@ -236,6 +237,60 @@ namespace Borepin.PageModel
}
}
}
private ICommand _UnlockLockCommand;
public ICommand UnlockLockCommand
{
get => _UnlockLockCommand;
set => SetProperty(ref _UnlockLockCommand, value);
}
public async void UnlockLockCommandExecute()
{
IsBusy = true;
if (_API.IsConnected)
{
try
{
Machine.IProdInterface prodInterface = _Machine.Prodable;
await prodInterface.ProdWithData(Encoding.ASCII.GetBytes("action: unlock")).ConfigureAwait(false);
}
catch (RpcException exception) when (string.Equals(exception.Message, "RPC connection is broken. Task would never return.", StringComparison.Ordinal))
{
Log.Debug("RPC Connection Loss");
}
}
IsBusy = false;
}
private ICommand _IdentifyLockCommand;
public ICommand IdentifyLockCommand
{
get => _IdentifyLockCommand;
set => SetProperty(ref _IdentifyLockCommand, value);
}
public async void IdentifyLockCommandExecute()
{
IsBusy = true;
if (_API.IsConnected)
{
try
{
Machine.IProdInterface prodInterface = _Machine.Prodable;
await prodInterface.ProdWithData(Encoding.ASCII.GetBytes("action: identify")).ConfigureAwait(false);
}
catch (RpcException exception) when (string.Equals(exception.Message, "RPC connection is broken. Task would never return.", StringComparison.Ordinal))
{
Log.Debug("RPC Connection Loss");
}
}
IsBusy = false;
}
#endregion
}
}

View File

@ -112,6 +112,13 @@ namespace Borepin.PageModel
get => _InstanceIsDefaultConnection;
set => SetProperty(ref _InstanceIsDefaultConnection, value);
}
private bool _TestConnection;
public bool TestConnection
{
get => _TestConnection;
set => SetProperty(ref _TestConnection, value);
}
#endregion
#region Commands
@ -124,8 +131,9 @@ namespace Borepin.PageModel
public async Task ConnectCommandExecute()
{
IsBusy = true;
TestConnection = true;
if(_API.IsConnected)
if (_API.IsConnected)
{
await _API.Disconnect().ConfigureAwait(true);
}
@ -137,6 +145,8 @@ namespace Borepin.PageModel
catch(Exception exception)
{
_ErrorMessageService.DisplayConnectFailedMessage(exception);
TestConnection = false;
IsBusy = false;
return;
}
@ -151,6 +161,9 @@ namespace Borepin.PageModel
Log.Fatal(result.Exception, "Navigating failed");
}
});
TestConnection = false;
IsBusy = false;
}
private ICommand _SetDefaultCommand;
public ICommand SetDefaultCommand

View File

@ -16,6 +16,7 @@ using NaturalSort.Extension;
using System.Linq;
using Prism.Services.Dialogs;
using Xamarin.Forms;
using ZXing;
namespace Borepin.PageModel
{
@ -34,6 +35,8 @@ namespace Borepin.PageModel
_DialogService = dialogService;
DeleteCommand = new DelegateCommand(DeleteCommandExecute);
UpdatePasswordCommand = new DelegateCommand(UpdatePasswordCommandExecute);
CreateCardCommand = new DelegateCommand(CreateCardCommandExecute);
UnbindCardCommand = new DelegateCommand(UnbindCardCommandExecute);
}
#endregion
@ -44,6 +47,10 @@ namespace Borepin.PageModel
{
_ID = instance as string;
}
else if (instance is CardConfig)
{
_ID = (instance as CardConfig).UserID;
}
else if(instance == null && _IsDialog)
{
@ -64,6 +71,11 @@ namespace Borepin.PageModel
}
_User = (await _API.Session.UserSystem.Search.GetUserByName(_ID).ConfigureAwait(false)).Just;
if(_User == null )
{
return;
}
UserItem = new UserVisualize(_User);
await UserItem.LoadData().ConfigureAwait(false);
@ -89,6 +101,13 @@ namespace Borepin.PageModel
CanAdmin = !((UserSystem.ManageInterface_Proxy)_API.Session.UserSystem.Manage).IsNull;
CanManage = !((User.ManageInterface_Proxy)_User.Manage).IsNull;
CanCreateCard = !((User.CardDESFireInterface_Proxy)_User.CardDESFireEV2).IsNull;
if(CanCreateCard)
{
IReadOnlyList<IReadOnlyList<byte>> list = await _User.CardDESFireEV2.GetTokenList().ConfigureAwait(false);
HasCardBinded = list != null && list.Count > 0;
}
}
#endregion
@ -121,6 +140,20 @@ namespace Borepin.PageModel
set => SetProperty(ref _CanManage, value);
}
private bool _CanCreateCard;
public bool CanCreateCard
{
get => _CanCreateCard;
set => SetProperty(ref _CanCreateCard, value);
}
private bool _HasCardBinded;
public bool HasCardBinded
{
get => _HasCardBinded;
set => SetProperty(ref _HasCardBinded, value);
}
private string _NewPassword;
public string NewPassword
{
@ -208,6 +241,60 @@ namespace Borepin.PageModel
}
IsBusy = false;
}
private ICommand _UnbindCardCommand;
public ICommand UnbindCardCommand
{
get => _UnbindCardCommand;
set => SetProperty(ref _UnbindCardCommand, value);
}
public async void UnbindCardCommandExecute()
{
IsBusy = true;
IReadOnlyList<IReadOnlyList<byte>> list = await _User.CardDESFireEV2.GetTokenList().ConfigureAwait(false);
if(list.Count > 0)
{
await _User.CardDESFireEV2.Unbind(list[0]).ConfigureAwait(false);
try
{
await LoadAPIData().ConfigureAwait(false);
}
catch
{
// TODO
}
}
IsBusy = false;
}
private ICommand _CreateCardCommand;
public ICommand CreateCardCommand
{
get => _CreateCardCommand;
set => SetProperty(ref _CreateCardCommand, value);
}
public void CreateCardCommandExecute()
{
IsBusy = true;
NavigationParameters parameters = new NavigationParameters
{
{ "instance", _ID },
};
Device.BeginInvokeOnMainThread(async () =>
{
INavigationResult result_nav = await _NavigationService.NavigateAsync("CreateCardPage", parameters).ConfigureAwait(false);
if (result_nav.Exception != null)
{
Log.Fatal(result_nav.Exception, "Navigating failed");
}
});
IsBusy = false;
}
#endregion
}
}

View File

@ -124,9 +124,9 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die FabAccess is a decentralized machine management system. Each Space thus uses its own server.
///Ask your Space for the address of your server.
///You can also put down several servers and then connect to the desired server. ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die FabAccess is a decentralized machine management system, which means that it is designed to allow each Space to have its own dedicated server for managing its machines. If you want to connect to the FabAccess server for a specific Space, you will need to obtain the host address from that particular Space.
///
///In addition to being able to connect to individual servers, FabAccess also allows you to add multiple servers to your account. This feature is especially useful for makers and innovators who have access [Rest der Zeichenfolge wurde abgeschnitten]&quot;; ähnelt.
/// </summary>
internal static string AddServerProcess_SelectServerPage_Info {
get {
@ -134,6 +134,24 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die test.fab-access.org ähnelt.
/// </summary>
internal static string AddServerProcess_SelectServerPage_Placeholder {
get {
return ResourceManager.GetString("AddServerProcess_SelectServerPage_Placeholder", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Trying to connect to the server ähnelt.
/// </summary>
internal static string AddServerProcess_SelectServerPage_TryConnection {
get {
return ResourceManager.GetString("AddServerProcess_SelectServerPage_TryConnection", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User ähnelt.
/// </summary>
@ -162,7 +180,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User failed ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Add User failed. ähnelt.
/// </summary>
internal static string ALERT_AddUserFailed {
get {
@ -171,7 +189,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Authentication failed ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Authentication failed. ähnelt.
/// </summary>
internal static string ALERT_AuthFailed {
get {
@ -189,7 +207,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die SASL Mechanism is not supported- ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die SASL Mechanism is not supported. ähnelt.
/// </summary>
internal static string ALERT_BadMechanism {
get {
@ -198,7 +216,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Connection failed ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Connection failed. ähnelt.
/// </summary>
internal static string ALERT_ConnectionFailed {
get {
@ -233,6 +251,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die ID is invalid. ähnelt.
/// </summary>
internal static string ALERT_ID {
get {
return ResourceManager.GetString("ALERT_ID", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Password is invalid. ähnelt.
/// </summary>
@ -306,7 +333,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die It&apos;s Bionade ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die It&apos;s Bionade! ähnelt.
/// </summary>
internal static string Bionade {
get {
@ -342,7 +369,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Connecting to Server ... ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Connecting to Server ähnelt.
/// </summary>
internal static string ConnectionStatus_Connecting {
get {
@ -450,8 +477,8 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die You do not have the authorization to use this machine.
///Ask in your Space if you can be trained on the machine to be unlocked for the machine. ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die You are not currently authorized to use this machine.
///Please speak with the staff at the Space to receive the necessary training and authorization. ähnelt.
/// </summary>
internal static string MachinePage_CanNotUseByPermission {
get {
@ -504,6 +531,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Identify ähnelt.
/// </summary>
internal static string MachinePage_Identify {
get {
return ResourceManager.GetString("MachinePage_Identify", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Last User: ähnelt.
/// </summary>
@ -711,6 +747,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die You can set a server as the default server and then the app will automatically connect to that server upon startup. ähnelt.
/// </summary>
internal static string ServerPage_DefaultText {
get {
return ResourceManager.GetString("ServerPage_DefaultText", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Disconnect ähnelt.
/// </summary>
@ -721,7 +766,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Is Default Connection ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die This connection has been set as the default and FabAccess will automatically connect to this server upon startup. ähnelt.
/// </summary>
internal static string ServerPage_IsDefault {
get {
@ -766,7 +811,9 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Automate your Space with FabAccess ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die FabAccess is a machine management system designed for makerspaces, fablab and other collaborative workspaces.
///
///With FabAccess, you can access and schedule machines, manage users and receive real-time updates on machine status and usage. The platform provides a decentralized solution for managing and connecting to machines across different Spaces, making it easier for users to collaborate and innovate together. ähnelt.
/// </summary>
internal static string SetUpProcess_WelcomePage_Text {
get {
@ -775,7 +822,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Welcome ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Welcome to FabAccess ähnelt.
/// </summary>
internal static string SetUpProcess_WelcomePage_Title {
get {
@ -901,7 +948,7 @@ namespace Borepin.Resources.Text {
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User ähnelt.
/// Sucht eine lokalisierte Zeichenfolge, die Add new User ähnelt.
/// </summary>
internal static string UserListPage_AddUser {
get {
@ -909,6 +956,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Search User ähnelt.
/// </summary>
internal static string UserListPage_Search {
get {
return ResourceManager.GetString("UserListPage_Search", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Search Username ... ähnelt.
/// </summary>
@ -936,6 +992,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Create new FabFire Card ähnelt.
/// </summary>
internal static string UserPage_CreateCard {
get {
return ResourceManager.GetString("UserPage_CreateCard", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die New Password ähnelt.
/// </summary>
@ -945,6 +1010,15 @@ namespace Borepin.Resources.Text {
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Unbind FabFire Card ähnelt.
/// </summary>
internal static string UserPage_UnbindCard {
get {
return ResourceManager.GetString("UserPage_UnbindCard", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Force Password Update ähnelt.
/// </summary>

View File

@ -139,9 +139,15 @@
<value>Connect to Server</value>
</data>
<data name="AddServerProcess_SelectServerPage_Info" xml:space="preserve">
<value>FabAccess is a decentralized machine management system. Each Space thus uses its own server.
Ask your Space for the address of your server.
You can also put down several servers and then connect to the desired server.</value>
<value>FabAccess is a decentralized machine management system, which means that it is designed to allow each Space to have its own dedicated server for managing its machines. If you want to connect to the FabAccess server for a specific Space, you will need to obtain the host address from that particular Space.
In addition to being able to connect to individual servers, FabAccess also allows you to add multiple servers to your account. This feature is especially useful for makers and innovators who have access to machines at multiple Spaces.</value>
</data>
<data name="AddServerProcess_SelectServerPage_Placeholder" xml:space="preserve">
<value>test.fab-access.org</value>
</data>
<data name="AddServerProcess_SelectServerPage_TryConnection" xml:space="preserve">
<value>Trying to connect to the server</value>
</data>
<data name="AddUserPage_AddUser" xml:space="preserve">
<value>Add User</value>
@ -154,11 +160,11 @@ You can also put down several servers and then connect to the desired server.</v
<comment>Message Content</comment>
</data>
<data name="ALERT_AddUserFailed" xml:space="preserve">
<value>Add User failed</value>
<value>Add User failed.</value>
<comment>Message Content</comment>
</data>
<data name="ALERT_AuthFailed" xml:space="preserve">
<value>Authentication failed</value>
<value>Authentication failed.</value>
<comment>Message Title</comment>
</data>
<data name="ALERT_AuthServer" xml:space="preserve">
@ -166,11 +172,11 @@ You can also put down several servers and then connect to the desired server.</v
<comment>Message Content</comment>
</data>
<data name="ALERT_BadMechanism" xml:space="preserve">
<value>SASL Mechanism is not supported-</value>
<value>SASL Mechanism is not supported.</value>
<comment>Message Content</comment>
</data>
<data name="ALERT_ConnectionFailed" xml:space="preserve">
<value>Connection failed</value>
<value>Connection failed.</value>
<comment>Message Title</comment>
</data>
<data name="ALERT_ConnectionTimeout" xml:space="preserve">
@ -185,6 +191,9 @@ You can also put down several servers and then connect to the desired server.</v
<value>Connection already exist. Please delete old Connection before adding the new Connection.</value>
<comment>Message Content</comment>
</data>
<data name="ALERT_ID" xml:space="preserve">
<value>ID is invalid.</value>
</data>
<data name="ALERT_PasswordInvalid" xml:space="preserve">
<value>Password is invalid.</value>
<comment>Message Content</comment>
@ -218,7 +227,7 @@ You can also put down several servers and then connect to the desired server.</v
<comment>Message Content</comment>
</data>
<data name="Bionade" xml:space="preserve">
<value>It's Bionade</value>
<value>It's Bionade!</value>
</data>
<data name="BUILD" xml:space="preserve">
<value>Build</value>
@ -230,7 +239,7 @@ You can also put down several servers and then connect to the desired server.</v
<value>Confirm</value>
</data>
<data name="ConnectionStatus_Connecting" xml:space="preserve">
<value>Connecting to Server ...</value>
<value>Connecting to Server</value>
</data>
<data name="ConnectionStatus_NoConnection" xml:space="preserve">
<value>No Connection to Server</value>
@ -266,8 +275,8 @@ You can also put down several servers and then connect to the desired server.</v
<value>Machine</value>
</data>
<data name="MachinePage_CanNotUseByPermission" xml:space="preserve">
<value>You do not have the authorization to use this machine.
Ask in your Space if you can be trained on the machine to be unlocked for the machine.</value>
<value>You are not currently authorized to use this machine.
Please speak with the staff at the Space to receive the necessary training and authorization.</value>
</data>
<data name="MachinePage_CurrentUser" xml:space="preserve">
<value>Current User:</value>
@ -284,6 +293,9 @@ Ask in your Space if you can be trained on the machine to be unlocked for the ma
<data name="MachinePage_GiveBack" xml:space="preserve">
<value>GiveBack</value>
</data>
<data name="MachinePage_Identify" xml:space="preserve">
<value>Identify</value>
</data>
<data name="MachinePage_LastUser" xml:space="preserve">
<value>Last User:</value>
</data>
@ -356,11 +368,14 @@ Ask in your Space if you can be trained on the machine to be unlocked for the ma
<data name="ServerPage_Connect" xml:space="preserve">
<value>Connect</value>
</data>
<data name="ServerPage_DefaultText" xml:space="preserve">
<value>You can set a server as the default server and then the app will automatically connect to that server upon startup.</value>
</data>
<data name="ServerPage_Disconnect" xml:space="preserve">
<value>Disconnect</value>
</data>
<data name="ServerPage_IsDefault" xml:space="preserve">
<value>Is Default Connection</value>
<value>This connection has been set as the default and FabAccess will automatically connect to this server upon startup.</value>
</data>
<data name="ServerPage_SetDefault" xml:space="preserve">
<value>Set as Default Connection</value>
@ -372,10 +387,12 @@ Ask in your Space if you can be trained on the machine to be unlocked for the ma
<value>Begin working</value>
</data>
<data name="SetUpProcess_WelcomePage_Text" xml:space="preserve">
<value>Automate your Space with FabAccess</value>
<value>FabAccess is a machine management system designed for makerspaces, fablab and other collaborative workspaces.
With FabAccess, you can access and schedule machines, manage users and receive real-time updates on machine status and usage. The platform provides a decentralized solution for managing and connecting to machines across different Spaces, making it easier for users to collaborate and innovate together.</value>
</data>
<data name="SetUpProcess_WelcomePage_Title" xml:space="preserve">
<value>Welcome</value>
<value>Welcome to FabAccess</value>
</data>
<data name="StartPage_Connecting" xml:space="preserve">
<value>Connecting to Server</value>
@ -417,7 +434,10 @@ Ask in your Space if you can be trained on the machine to be unlocked for the ma
<value>Uncategorised</value>
</data>
<data name="UserListPage_AddUser" xml:space="preserve">
<value>Add User</value>
<value>Add new User</value>
</data>
<data name="UserListPage_Search" xml:space="preserve">
<value>Search User</value>
</data>
<data name="UserListPage_SearchUser" xml:space="preserve">
<value>Search Username ...</value>
@ -428,9 +448,15 @@ Ask in your Space if you can be trained on the machine to be unlocked for the ma
<data name="UserPage_ChangePassword" xml:space="preserve">
<value>Update Password</value>
</data>
<data name="UserPage_CreateCard" xml:space="preserve">
<value>Create new FabFire Card</value>
</data>
<data name="UserPage_NewPassword" xml:space="preserve">
<value>New Password</value>
</data>
<data name="UserPage_UnbindCard" xml:space="preserve">
<value>Unbind FabFire Card</value>
</data>
<data name="UserPage_UpdatePassword" xml:space="preserve">
<value>Force Password Update</value>
</data>

View File

@ -13,7 +13,7 @@
<ContentView.Content>
<StackLayout>
<StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator>
<ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout>
<StackLayout>
@ -23,9 +23,10 @@
<Binding Path="IsConnected" Converter="{StaticResource InvertBoolConverter}"/>
</MultiBinding>
</StackLayout.IsVisible>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_NoConnection}"/>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_Connecting}" IsVisible="{Binding IsConnecting}"/>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_NotConnected}" IsVisible="{Binding IsConnecting, Converter={StaticResource InvertBoolConverter}}"/>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_NoConnection}" Style="{StaticResource Style_Label_Text_Center}"/>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_Connecting}" IsVisible="{Binding IsConnecting}" Style="{StaticResource Style_Label_Text_Center}"/>
<ActivityIndicator IsRunning="{Binding IsConnecting}" IsVisible="{Binding IsConnecting}"/>
<Label Text="{x:Static resource_text:TextResource.ConnectionStatus_NotConnected}" IsVisible="{Binding IsConnecting, Converter={StaticResource InvertBoolConverter}}" Style="{StaticResource Style_Label_Text_Center}"/>
</StackLayout>
</StackLayout>
</ContentView.Content>

View File

@ -323,7 +323,14 @@ namespace FabAccessAPI
{
if(!IsConnected && CanConnect)
{
await Connect(ConnectionData).ConfigureAwait(false);
try
{
await Connect(ConnectionData).ConfigureAwait(false);
}
catch(AuthenticationException)
{
await Disconnect().ConfigureAwait(false);
}
}
}
@ -346,7 +353,7 @@ namespace FabAccessAPI
SslStream sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(_RemoteCertificateValidationCallback));
try
{
sslStream.ReadTimeout = 2000;
sslStream.ReadTimeout = 5000;
sslStream.AuthenticateAsClient("bffhd");
sslStream.ReadTimeout = -1;
@ -376,7 +383,7 @@ namespace FabAccessAPI
try
{
Task timeoutTask = Task.Delay(3000);
Task timeoutTask = Task.Delay(5000);
tcprpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port);
await await Task.WhenAny(tcprpcClient.WhenConnected, timeoutTask);

@ -1 +1 @@
Subproject commit 19f20f5154f0eced6288ff56cac840025ee51da1
Subproject commit cde4677575f8e133ac764663e131c80fc891d545

View File

@ -1,4 +1,5 @@
using FabAccessAPI;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@ -11,6 +12,7 @@ namespace FabAccessAPI_Test
public const int TESTSERVER_PORT = 59661;
public const string PASSWORD = "secret";
[TestCase("Testuser")]
public static ConnectionData CreateConnetionData(string username)
{
ConnectionData connectionData = new ConnectionData()

2
external/NFC vendored

@ -1 +1 @@
Subproject commit e79b6aace26c8b362a5f450345a67ba700f06805
Subproject commit a6479be14e86add7a84b3a1a502608a665ec51f0