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 EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI_Test", "FabAccessAPI_Test\FabAccessAPI_Test.csproj", "{1C85978A-9FC0-4064-8399-FA2455C5EC2A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI_Test", "FabAccessAPI_Test\FabAccessAPI_Test.csproj", "{1C85978A-9FC0-4064-8399-FA2455C5EC2A}"
EndProject 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borepin_Test", "Borepin_Test\Borepin_Test.csproj", "{A959A406-91A5-4D81-B90D-EF022812D97D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EA0AA4A-A814-45A0-9EA7-E9147CCCCB6A}" 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Borepin.GTK\Borepin.GTK.csproj", "{61D956D2-5819-4736-BBD8-AD8208DE6A62}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Borepin.GTK\Borepin.GTK.csproj", "{61D956D2-5819-4736-BBD8-AD8208DE6A62}"
EndProject 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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|x64.Build.0 = Release|Any CPU
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|x86.ActiveCfg = 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 {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.ActiveCfg = Debug|Any CPU
{A959A406-91A5-4D81-B90D-EF022812D97D}.Debug|Any CPU.Build.0 = 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 {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|x64.Build.0 = Release|Any CPU
{61D956D2-5819-4736-BBD8-AD8208DE6A62}.Release|x86.ActiveCfg = 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 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,12 +1,23 @@
 using Android.App;
using Android.App; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
using Android.OS; using Android.OS;
using AndroidX.AppCompat.App; using AndroidX.AppCompat.App;
namespace Borepin.Droid 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 public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{ {
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
@ -24,6 +35,15 @@ namespace Borepin.Droid
Xamarin.Forms.Forms.Init(this, savedInstanceState); Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App(new PlatformInitializer())); 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) 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")] [Application(Label = "FabAccess", Icon = "@mipmap/ic_launcher")]
public class MainApplication : Application public class MainApplication : Application
{ {
public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
: base(javaReference, transfer)
{ {
} }
} }
} }

View File

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

View File

@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?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"> <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" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<application android:theme="@style/MainTheme" android:label="FabAccess" android:networkSecurityConfig="@xml/network_security_config"></application> <application android:theme="@style/MainTheme" android:label="FabAccess" android:networkSecurityConfig="@xml/network_security_config">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> </application>
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" /> <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> </manifest>

View File

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

View File

@ -187,9 +187,17 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\external\capnproto-dotnetcore\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj"> <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> <Name>Capnp.Net.Runtime</Name>
</ProjectReference> </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"> <ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj">
<Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project> <Project>{3251FCE9-FEA3-4662-8BEB-636BE6732D48}</Project>
<Name>FabAccessAPI</Name> <Name>FabAccessAPI</Name>

View File

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

View File

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

View File

@ -42,5 +42,18 @@
<string>Light</string> <string>Light</string>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>Please allow access to the camera to scan barcodes</string> <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> </dict>
</plist> </plist>

View File

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

View File

@ -13,6 +13,14 @@ using System;
using Borepin.Service.Storage; using Borepin.Service.Storage;
using NLog; using NLog;
using Borepin.Service.ErrorMessage; 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 namespace Borepin
{ {
@ -20,8 +28,8 @@ namespace Borepin
{ {
public App(IPlatformInitializer platformInitializer) : base(platformInitializer) public App(IPlatformInitializer platformInitializer) : base(platformInitializer)
{ {
var config = new NLog.Config.LoggingConfiguration(); NLog.Config.LoggingConfiguration config = new NLog.Config.LoggingConfiguration();
var logconsole = new NLog.Targets.ConsoleTarget("logconsole"); NLog.Targets.ConsoleTarget logconsole = new NLog.Targets.ConsoleTarget("logconsole");
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logconsole); config.AddRule(LogLevel.Trace, LogLevel.Fatal, logconsole);
LogManager.Configuration = config; LogManager.Configuration = config;
} }
@ -33,6 +41,52 @@ namespace Borepin
await NavigationService.NavigateAsync(new Uri("https://borepin.fab-access.org/StartPage")).ConfigureAwait(false); 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) protected override void RegisterTypes(IContainerRegistry containerRegistry)
{ {
#region Register Basic Navigation #region Register Basic Navigation
@ -51,6 +105,7 @@ namespace Borepin
containerRegistry.RegisterForNavigation<UserListPage, UserListPageModel>(); containerRegistry.RegisterForNavigation<UserListPage, UserListPageModel>();
containerRegistry.RegisterForNavigation<UserPage, UserPageModel>(); containerRegistry.RegisterForNavigation<UserPage, UserPageModel>();
containerRegistry.RegisterForNavigation<CreateCardPage, CreateCardPageModel>();
containerRegistry.RegisterForNavigation<AddUserPage, AddUserPageModel>(); containerRegistry.RegisterForNavigation<AddUserPage, AddUserPageModel>();
containerRegistry.RegisterForNavigation<ProfilePage, ProfilePageModel>(); containerRegistry.RegisterForNavigation<ProfilePage, ProfilePageModel>();
#endregion #endregion

View File

@ -111,6 +111,9 @@
<EmbeddedResource Update="Page\AddUserPage.xaml"> <EmbeddedResource Update="Page\AddUserPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="Page\CreateCardPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Page\MachinePage.xaml"> <EmbeddedResource Update="Page\MachinePage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource> </EmbeddedResource>
@ -156,6 +159,7 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\external\NFC\NFC\NFC.csproj" />
<ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj" /> <ProjectReference Include="..\..\FabAccessAPI\FabAccessAPI.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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 #region Methods
public async Task LoadData() public async Task LoadData()
{ {
if(_Machine== null)
{
return;
}
//ID = _Machine.Id; //ID = _Machine.Id;
//Space = new SpaceVisualize(_Machine.Space); //Space = new SpaceVisualize(_Machine.Space);
Name = _Machine.Name; Name = _Machine.Name;
@ -75,6 +80,7 @@ namespace Borepin.Model
CanManage = !((ManageInterface_Proxy)_Machine.Manage).IsNull; CanManage = !((ManageInterface_Proxy)_Machine.Manage).IsNull;
CanAdmin = !((AdminInterface_Proxy)_Machine.Admin).IsNull; CanAdmin = !((AdminInterface_Proxy)_Machine.Admin).IsNull;
CanNotUseByPermission = State == MachineState.free && !CanUse; CanNotUseByPermission = State == MachineState.free && !CanUse;
IsLock = !((ProdInterface_Proxy)_Machine.Prodable).IsNull;
} }
#endregion #endregion
@ -197,6 +203,13 @@ namespace Borepin.Model
get => _CanNotUseByPermission; get => _CanNotUseByPermission;
set => SetProperty(ref _CanNotUseByPermission, value); set => SetProperty(ref _CanNotUseByPermission, value);
} }
private bool _IsLock;
public bool IsLock
{
get => _IsLock;
set => SetProperty(ref _IsLock, value);
}
#endregion #endregion
} }
} }

View File

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

View File

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

View File

@ -13,7 +13,7 @@
<ContentPage.Content> <ContentPage.Content>
<StackLayout Padding="20"> <StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}"> <StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator> <ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout> </StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}"> <StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.AddServerProcess_ChooseAuthTypePage_SignIn}" Style="{StaticResource Style_Label_Property_Title}"></Label> <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.Resources>
<ContentPage.Content> <ContentPage.Content>
<StackLayout Padding="20"> <StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}"> <StackLayout>
<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}" IsVisible="{Binding IsBusy}"/>
</StackLayout> </StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}"> <StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}">
<Label Text="{x:Static resource_text:TextResource.HOST}" Style="{StaticResource Style_Label_Property_Title}"></Label> <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.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 Text="{x:Static resource_text:TextResource.SCANQR}" Command="{Binding ScanCodeCommand}" Style="{StaticResource Style_Button_Primary}">
<Button.IsVisible> <Button.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean" <OnPlatform x:TypeArguments="x:Boolean">
iOS="true" <On Platform="iOS" Value="True" />
Android="true"/> <On Platform="Android" Value="True" />
<On Platform="UWP" Value="False" />
</OnPlatform>
</Button.IsVisible> </Button.IsVisible>
</Button> </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>
</StackLayout> </StackLayout>
</ContentPage.Content> </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> </MultiBinding>
</StackLayout.IsVisible> </StackLayout.IsVisible>
<Button Text="{x:Static resource_text:TextResource.SCANQR}" Command="{Binding ScanCodeCommand}" Style="{StaticResource Style_Button_Primary}"> <Button Text="{x:Static resource_text:TextResource.SCANQR}" Command="{Binding ScanCodeCommand}" Style="{StaticResource Style_Button_Primary}">
<Button.IsVisible> <Button.IsVisible>
<OnPlatform x:TypeArguments="x:Boolean" <OnPlatform x:TypeArguments="x:Boolean">
iOS="True" <On Platform="iOS" Value="True" />
Android="True"/> <On Platform="Android" Value="True" />
</Button.IsVisible> <On Platform="UWP" Value="False" />
</Button> </OnPlatform>
</Button.IsVisible>
</Button>
<ListView ItemsSource="{Binding MachineListItemViewModel_List}" SelectionMode="None" SeparatorColor="Transparent" IsGroupingEnabled="True" GroupDisplayBinding="{Binding Category}"> <ListView ItemsSource="{Binding MachineListItemViewModel_List}" SelectionMode="None" SeparatorColor="Transparent" IsGroupingEnabled="True" GroupDisplayBinding="{Binding Category}">
<ListView.GroupHeaderTemplate> <ListView.GroupHeaderTemplate>
<DataTemplate> <DataTemplate>

View File

@ -43,15 +43,23 @@
<Label Text="{Binding MachineItem.CurrentUser.Username}" Style="{StaticResource Style_Label_Property_Text}"/> <Label Text="{Binding MachineItem.CurrentUser.Username}" Style="{StaticResource Style_Label_Property_Text}"/>
</StackLayout> </StackLayout>
<Button Text="{x:Static resource_text:TextResource.MachinePage_Use}" IsVisible="{Binding MachineItem.CanUse}" Command="{Binding UseMachineCommand}" Style="{StaticResource Style_Button_Primary}"/> <StackLayout>
<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_Use}" IsVisible="{Binding MachineItem.CanUse}" Command="{Binding UseMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<Button Text="{x:Static resource_text:TextResource.MachinePage_GiveBack}" IsVisible="{Binding MachineItem.CanInUse}" Command="{Binding GiveBackMachineCommand}" 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 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}"/> <Button Text="{x:Static resource_text:TextResource.MachinePage_GiveBack}" IsVisible="{Binding MachineItem.CanInUse}" Command="{Binding GiveBackMachineCommand}" Style="{StaticResource Style_Button_Primary}"/>
<StackLayout Grid.Row="2" VerticalOptions="End" IsVisible="{Binding MachineItem.CanManage}"> </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}"/> <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="{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> </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_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}"/> <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> <ContentPage.Content>
<StackLayout Padding="20"> <StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}"> <StackLayout IsVisible="{Binding IsBusy}">
<ActivityIndicator IsRunning="{Binding IsBusy}"></ActivityIndicator> <ActivityIndicator IsRunning="{Binding IsBusy}"/>
</StackLayout> </StackLayout>
<StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand"> <StackLayout IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand">
<Label Text="{x:Static resource_text:TextResource.ServerListPage_ActiveConnection}" IsVisible="{Binding HasActiveConnection}"/> <Label Text="{x:Static resource_text:TextResource.ServerListPage_ActiveConnection}" IsVisible="{Binding HasActiveConnection}"/>

View File

@ -13,7 +13,8 @@
<ContentPage.Content> <ContentPage.Content>
<StackLayout Padding="20"> <StackLayout Padding="20">
<StackLayout IsVisible="{Binding IsBusy}"> <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>
<Grid IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand"> <Grid IsVisible="{Binding IsBusy, Converter={StaticResource InvertBoolConverter}}" VerticalOptions="FillAndExpand">
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -23,8 +24,11 @@
<StackLayout Grid.Row="0"> <StackLayout Grid.Row="0">
<Label Text="{Binding DisplayAddress}" Style="{StaticResource LabelStyle_Title}"/> <Label Text="{Binding DisplayAddress}" Style="{StaticResource LabelStyle_Title}"/>
<Label Text="{Binding Connection_Item.Username}" Style="{StaticResource Style_Label_Text_Center}"/> <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}"/> <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, 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}"/> <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> </StackLayout>

View File

@ -27,7 +27,7 @@
</MultiBinding> </MultiBinding>
</StackLayout.IsVisible> </StackLayout.IsVisible>
<Button Text="{x:Static resource_text:TextResource.UserListPage_AddUser}" Command="{Binding AddUserCommand}" Style="{StaticResource Style_Button_Primary}"/> <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> <SearchBar.Behaviors>
<prism:EventToCommandBehavior EventName="TextChanged" Command="{Binding SearchUserCommand}"/> <prism:EventToCommandBehavior EventName="TextChanged" Command="{Binding SearchUserCommand}"/>
</SearchBar.Behaviors> </SearchBar.Behaviors>

View File

@ -22,7 +22,7 @@
<StackLayout.IsVisible> <StackLayout.IsVisible>
<MultiBinding Converter="{StaticResource AllTrueBoolConverter}"> <MultiBinding Converter="{StaticResource AllTrueBoolConverter}">
<Binding Path="IsBusy" Converter="{StaticResource InvertBoolConverter}"/> <Binding Path="IsBusy" Converter="{StaticResource InvertBoolConverter}"/>
<Binding Path="IsConnected" /> <Binding Path="IsConnected"/>
</MultiBinding> </MultiBinding>
</StackLayout.IsVisible> </StackLayout.IsVisible>
<Label Text="{Binding UserItem.Username}" Style="{StaticResource LabelStyle_Title}"/> <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}"/> <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}"/> <Button Text="{x:Static resource_text:TextResource.UserPage_UpdatePassword}" Command="{Binding UpdatePasswordCommand}" Style="{StaticResource Style_Button_Primary}"/>
</StackLayout> </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>
</StackLayout> </StackLayout>
</ContentPage.Content> </ContentPage.Content>

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@ using NaturalSort.Extension;
using System.Linq; using System.Linq;
using Prism.Services.Dialogs; using Prism.Services.Dialogs;
using Xamarin.Forms; using Xamarin.Forms;
using ZXing;
namespace Borepin.PageModel namespace Borepin.PageModel
{ {
@ -34,6 +35,8 @@ namespace Borepin.PageModel
_DialogService = dialogService; _DialogService = dialogService;
DeleteCommand = new DelegateCommand(DeleteCommandExecute); DeleteCommand = new DelegateCommand(DeleteCommandExecute);
UpdatePasswordCommand = new DelegateCommand(UpdatePasswordCommandExecute); UpdatePasswordCommand = new DelegateCommand(UpdatePasswordCommandExecute);
CreateCardCommand = new DelegateCommand(CreateCardCommandExecute);
UnbindCardCommand = new DelegateCommand(UnbindCardCommandExecute);
} }
#endregion #endregion
@ -44,6 +47,10 @@ namespace Borepin.PageModel
{ {
_ID = instance as string; _ID = instance as string;
} }
else if (instance is CardConfig)
{
_ID = (instance as CardConfig).UserID;
}
else if(instance == null && _IsDialog) else if(instance == null && _IsDialog)
{ {
@ -64,6 +71,11 @@ namespace Borepin.PageModel
} }
_User = (await _API.Session.UserSystem.Search.GetUserByName(_ID).ConfigureAwait(false)).Just; _User = (await _API.Session.UserSystem.Search.GetUserByName(_ID).ConfigureAwait(false)).Just;
if(_User == null )
{
return;
}
UserItem = new UserVisualize(_User); UserItem = new UserVisualize(_User);
await UserItem.LoadData().ConfigureAwait(false); await UserItem.LoadData().ConfigureAwait(false);
@ -89,6 +101,13 @@ namespace Borepin.PageModel
CanAdmin = !((UserSystem.ManageInterface_Proxy)_API.Session.UserSystem.Manage).IsNull; CanAdmin = !((UserSystem.ManageInterface_Proxy)_API.Session.UserSystem.Manage).IsNull;
CanManage = !((User.ManageInterface_Proxy)_User.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 #endregion
@ -121,6 +140,20 @@ namespace Borepin.PageModel
set => SetProperty(ref _CanManage, value); 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; private string _NewPassword;
public string NewPassword public string NewPassword
{ {
@ -208,6 +241,60 @@ namespace Borepin.PageModel
} }
IsBusy = false; 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 #endregion
} }
} }

View File

@ -124,9 +124,9 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die FabAccess is a decentralized machine management system. Each Space thus uses its own server. /// 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.
///Ask your Space for the address of your server. ///
///You can also put down several servers and then connect to the desired server. ähnelt. ///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> /// </summary>
internal static string AddServerProcess_SelectServerPage_Info { internal static string AddServerProcess_SelectServerPage_Info {
get { 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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Add User ähnelt.
/// </summary> /// </summary>
@ -162,7 +180,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User failed ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Add User failed. ähnelt.
/// </summary> /// </summary>
internal static string ALERT_AddUserFailed { internal static string ALERT_AddUserFailed {
get { get {
@ -171,7 +189,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Authentication failed ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Authentication failed. ähnelt.
/// </summary> /// </summary>
internal static string ALERT_AuthFailed { internal static string ALERT_AuthFailed {
get { get {
@ -189,7 +207,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die SASL Mechanism is not supported- ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die SASL Mechanism is not supported. ähnelt.
/// </summary> /// </summary>
internal static string ALERT_BadMechanism { internal static string ALERT_BadMechanism {
get { get {
@ -198,7 +216,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Connection failed ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Connection failed. ähnelt.
/// </summary> /// </summary>
internal static string ALERT_ConnectionFailed { internal static string ALERT_ConnectionFailed {
get { 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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Password is invalid. ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Password is invalid. ähnelt.
/// </summary> /// </summary>
@ -306,7 +333,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die It&apos;s Bionade ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die It&apos;s Bionade! ähnelt.
/// </summary> /// </summary>
internal static string Bionade { internal static string Bionade {
get { get {
@ -342,7 +369,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Connecting to Server ... ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Connecting to Server ähnelt.
/// </summary> /// </summary>
internal static string ConnectionStatus_Connecting { internal static string ConnectionStatus_Connecting {
get { get {
@ -450,8 +477,8 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die You do not have the authorization to use this machine. /// Sucht eine lokalisierte Zeichenfolge, die You are not currently authorized to use this machine.
///Ask in your Space if you can be trained on the machine to be unlocked for the machine. ähnelt. ///Please speak with the staff at the Space to receive the necessary training and authorization. ähnelt.
/// </summary> /// </summary>
internal static string MachinePage_CanNotUseByPermission { internal static string MachinePage_CanNotUseByPermission {
get { 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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Last User: ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Last User: ähnelt.
/// </summary> /// </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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Disconnect ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Disconnect ähnelt.
/// </summary> /// </summary>
@ -721,7 +766,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <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> /// </summary>
internal static string ServerPage_IsDefault { internal static string ServerPage_IsDefault {
get { get {
@ -766,7 +811,9 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <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> /// </summary>
internal static string SetUpProcess_WelcomePage_Text { internal static string SetUpProcess_WelcomePage_Text {
get { get {
@ -775,7 +822,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Welcome ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Welcome to FabAccess ähnelt.
/// </summary> /// </summary>
internal static string SetUpProcess_WelcomePage_Title { internal static string SetUpProcess_WelcomePage_Title {
get { get {
@ -901,7 +948,7 @@ namespace Borepin.Resources.Text {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Add User ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Add new User ähnelt.
/// </summary> /// </summary>
internal static string UserListPage_AddUser { internal static string UserListPage_AddUser {
get { 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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Search Username ... ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Search Username ... ähnelt.
/// </summary> /// </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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die New Password ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die New Password ähnelt.
/// </summary> /// </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> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Force Password Update ähnelt. /// Sucht eine lokalisierte Zeichenfolge, die Force Password Update ähnelt.
/// </summary> /// </summary>

View File

@ -139,9 +139,15 @@
<value>Connect to Server</value> <value>Connect to Server</value>
</data> </data>
<data name="AddServerProcess_SelectServerPage_Info" xml:space="preserve"> <data name="AddServerProcess_SelectServerPage_Info" xml:space="preserve">
<value>FabAccess is a decentralized machine management system. Each Space thus uses its own server. <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.
Ask your Space for the address of your server.
You can also put down several servers and then connect to the desired server.</value> 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>
<data name="AddUserPage_AddUser" xml:space="preserve"> <data name="AddUserPage_AddUser" xml:space="preserve">
<value>Add User</value> <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> <comment>Message Content</comment>
</data> </data>
<data name="ALERT_AddUserFailed" xml:space="preserve"> <data name="ALERT_AddUserFailed" xml:space="preserve">
<value>Add User failed</value> <value>Add User failed.</value>
<comment>Message Content</comment> <comment>Message Content</comment>
</data> </data>
<data name="ALERT_AuthFailed" xml:space="preserve"> <data name="ALERT_AuthFailed" xml:space="preserve">
<value>Authentication failed</value> <value>Authentication failed.</value>
<comment>Message Title</comment> <comment>Message Title</comment>
</data> </data>
<data name="ALERT_AuthServer" xml:space="preserve"> <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> <comment>Message Content</comment>
</data> </data>
<data name="ALERT_BadMechanism" xml:space="preserve"> <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> <comment>Message Content</comment>
</data> </data>
<data name="ALERT_ConnectionFailed" xml:space="preserve"> <data name="ALERT_ConnectionFailed" xml:space="preserve">
<value>Connection failed</value> <value>Connection failed.</value>
<comment>Message Title</comment> <comment>Message Title</comment>
</data> </data>
<data name="ALERT_ConnectionTimeout" xml:space="preserve"> <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> <value>Connection already exist. Please delete old Connection before adding the new Connection.</value>
<comment>Message Content</comment> <comment>Message Content</comment>
</data> </data>
<data name="ALERT_ID" xml:space="preserve">
<value>ID is invalid.</value>
</data>
<data name="ALERT_PasswordInvalid" xml:space="preserve"> <data name="ALERT_PasswordInvalid" xml:space="preserve">
<value>Password is invalid.</value> <value>Password is invalid.</value>
<comment>Message Content</comment> <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> <comment>Message Content</comment>
</data> </data>
<data name="Bionade" xml:space="preserve"> <data name="Bionade" xml:space="preserve">
<value>It's Bionade</value> <value>It's Bionade!</value>
</data> </data>
<data name="BUILD" xml:space="preserve"> <data name="BUILD" xml:space="preserve">
<value>Build</value> <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> <value>Confirm</value>
</data> </data>
<data name="ConnectionStatus_Connecting" xml:space="preserve"> <data name="ConnectionStatus_Connecting" xml:space="preserve">
<value>Connecting to Server ...</value> <value>Connecting to Server</value>
</data> </data>
<data name="ConnectionStatus_NoConnection" xml:space="preserve"> <data name="ConnectionStatus_NoConnection" xml:space="preserve">
<value>No Connection to Server</value> <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> <value>Machine</value>
</data> </data>
<data name="MachinePage_CanNotUseByPermission" xml:space="preserve"> <data name="MachinePage_CanNotUseByPermission" xml:space="preserve">
<value>You do not have the authorization to use this machine. <value>You are not currently authorized to use this machine.
Ask in your Space if you can be trained on the machine to be unlocked for the machine.</value> Please speak with the staff at the Space to receive the necessary training and authorization.</value>
</data> </data>
<data name="MachinePage_CurrentUser" xml:space="preserve"> <data name="MachinePage_CurrentUser" xml:space="preserve">
<value>Current User:</value> <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"> <data name="MachinePage_GiveBack" xml:space="preserve">
<value>GiveBack</value> <value>GiveBack</value>
</data> </data>
<data name="MachinePage_Identify" xml:space="preserve">
<value>Identify</value>
</data>
<data name="MachinePage_LastUser" xml:space="preserve"> <data name="MachinePage_LastUser" xml:space="preserve">
<value>Last User:</value> <value>Last User:</value>
</data> </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"> <data name="ServerPage_Connect" xml:space="preserve">
<value>Connect</value> <value>Connect</value>
</data> </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"> <data name="ServerPage_Disconnect" xml:space="preserve">
<value>Disconnect</value> <value>Disconnect</value>
</data> </data>
<data name="ServerPage_IsDefault" xml:space="preserve"> <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>
<data name="ServerPage_SetDefault" xml:space="preserve"> <data name="ServerPage_SetDefault" xml:space="preserve">
<value>Set as Default Connection</value> <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> <value>Begin working</value>
</data> </data>
<data name="SetUpProcess_WelcomePage_Text" xml:space="preserve"> <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>
<data name="SetUpProcess_WelcomePage_Title" xml:space="preserve"> <data name="SetUpProcess_WelcomePage_Title" xml:space="preserve">
<value>Welcome</value> <value>Welcome to FabAccess</value>
</data> </data>
<data name="StartPage_Connecting" xml:space="preserve"> <data name="StartPage_Connecting" xml:space="preserve">
<value>Connecting to Server</value> <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> <value>Uncategorised</value>
</data> </data>
<data name="UserListPage_AddUser" xml:space="preserve"> <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>
<data name="UserListPage_SearchUser" xml:space="preserve"> <data name="UserListPage_SearchUser" xml:space="preserve">
<value>Search Username ...</value> <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"> <data name="UserPage_ChangePassword" xml:space="preserve">
<value>Update Password</value> <value>Update Password</value>
</data> </data>
<data name="UserPage_CreateCard" xml:space="preserve">
<value>Create new FabFire Card</value>
</data>
<data name="UserPage_NewPassword" xml:space="preserve"> <data name="UserPage_NewPassword" xml:space="preserve">
<value>New Password</value> <value>New Password</value>
</data> </data>
<data name="UserPage_UnbindCard" xml:space="preserve">
<value>Unbind FabFire Card</value>
</data>
<data name="UserPage_UpdatePassword" xml:space="preserve"> <data name="UserPage_UpdatePassword" xml:space="preserve">
<value>Force Password Update</value> <value>Force Password Update</value>
</data> </data>

View File

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

View File

@ -323,7 +323,14 @@ namespace FabAccessAPI
{ {
if(!IsConnected && CanConnect) 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)); SslStream sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(_RemoteCertificateValidationCallback));
try try
{ {
sslStream.ReadTimeout = 2000; sslStream.ReadTimeout = 5000;
sslStream.AuthenticateAsClient("bffhd"); sslStream.AuthenticateAsClient("bffhd");
sslStream.ReadTimeout = -1; sslStream.ReadTimeout = -1;
@ -376,7 +383,7 @@ namespace FabAccessAPI
try try
{ {
Task timeoutTask = Task.Delay(3000); Task timeoutTask = Task.Delay(5000);
tcprpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port); tcprpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port);
await await Task.WhenAny(tcprpcClient.WhenConnected, timeoutTask); await await Task.WhenAny(tcprpcClient.WhenConnected, timeoutTask);

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

View File

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

2
external/NFC vendored

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