mirror of
https://gitlab.com/fabinfra/fabaccess/borepin.git
synced 2025-03-12 23:01:52 +01:00
Merged: master
This commit is contained in:
commit
1ad79b7c03
139
.gitlab-ci.yml
Normal file
139
.gitlab-ci.yml
Normal file
@ -0,0 +1,139 @@
|
||||
# This file is a template, and might need editing before it works on your project.
|
||||
# The following script will work for any project that can be built from command line by msbuild
|
||||
# It uses powershell shell executor, so you need to add the following line to your config.toml file
|
||||
# (located in gitlab-runner.exe directory):
|
||||
# shell = "powershell"
|
||||
#
|
||||
# The script is composed of 3 stages: build, test and deploy.
|
||||
#
|
||||
# The build stage restores NuGet packages and uses msbuild to build the exe and msi
|
||||
# One major issue you'll find is that you can't build msi projects from command line
|
||||
# if you use vdproj. There are workarounds building msi via devenv, but they rarely work
|
||||
# The best solution is migrating your vdproj projects to WiX, as it can be build directly
|
||||
# by msbuild.
|
||||
#
|
||||
# The test stage runs nunit from command line against Test project inside your solution
|
||||
# It also saves the resulting TestResult.xml file
|
||||
#
|
||||
# The deploy stage copies the exe and msi from build stage to a network drive
|
||||
# You need to have the network drive mapped as Local System user for gitlab-runner service to see it
|
||||
# The best way to persist the mapping is via a scheduled task (see: https://stackoverflow.com/a/7867064/1288473),
|
||||
# running the following batch command: net use P: \\x.x.x.x\Projects /u:your_user your_pass /persistent:yes
|
||||
|
||||
|
||||
# place project specific paths in variables to make the rest of the script more generic
|
||||
variables:
|
||||
LIB_RELEASE_FOLDER: 'Borepin\Borepin\bin\Release'
|
||||
UWP_RELEASE_FOLDER: 'Borepin\Borepin.UWP\bin\x86\Release'
|
||||
TEST_FOLDER: 'Tests\bin\Release'
|
||||
# DEPLOY_FOLDER: 'P:\Projects\YourApp\Builds'
|
||||
NUGET_PATH: 'C:\NuGet\nuget.exe'
|
||||
DOTNET_PATH: 'C:\Program Files\dotnet\dotnet.exe'
|
||||
MSBUILD_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\msbuild.exe'
|
||||
NUNIT_PATH: 'C:\Program Files (x86)\NUnit.org\nunit-console\nunit3-console.exe'
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
build_base:
|
||||
stage: build
|
||||
tags:
|
||||
- xamarin
|
||||
- windows
|
||||
# only:
|
||||
# - tags # the build process will only be started by git tag commits
|
||||
script:
|
||||
- '& "$env:NUGET_PATH" restore' # restore Nuget dependencies
|
||||
- '& "$env:MSBUILD_PATH" /p:Configuration=Release /target:Borepin' # build the project
|
||||
artifacts:
|
||||
expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
|
||||
paths:
|
||||
- '$env:LIB_RELEASE_FOLDER' # saving exe to copy to deploy folder
|
||||
- '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
|
||||
|
||||
build_UWP:
|
||||
stage: build
|
||||
tags:
|
||||
- xamarin
|
||||
- windows
|
||||
# only:
|
||||
# - tags # the build process will only be started by git tag commits
|
||||
script:
|
||||
- '& "$env:NUGET_PATH" restore' # restore Nuget dependencies
|
||||
- '& "$env:MSBUILD_PATH" /p:Configuration=Release /target:Borepin_UWP' # build the project
|
||||
artifacts:
|
||||
expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
|
||||
paths:
|
||||
- '$env:UWP_RELEASE_FOLDER' # saving exe to copy to deploy folder
|
||||
- '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
|
||||
|
||||
build_Android:
|
||||
stage: build
|
||||
tags:
|
||||
- xamarin
|
||||
- windows
|
||||
# only:
|
||||
# - tags # the build process will only be started by git tag commits
|
||||
script:
|
||||
- '& "$env:NUGET_PATH" restore' # restore Nuget dependencies
|
||||
- '& "$env:MSBUILD_PATH" /p:Configuration=Release /target:Borepin_Android:PackageForAndroid /target:Borepin_Android:SignAndroidPackage' # build the project /p:AndroidKeyStore=True
|
||||
artifacts:
|
||||
expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
|
||||
paths:
|
||||
- Borepin/Borepin.Android/bin/Release/com.companyname.borepin-Signed.apk # saving apk to copy to deploy folder
|
||||
- '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
|
||||
|
||||
build_iOS:
|
||||
stage: build
|
||||
tags:
|
||||
- macos
|
||||
# only:
|
||||
# - tags # the build process will only be started by git tag commits
|
||||
script:
|
||||
- 'nuget restore' # restore Nuget dependencies
|
||||
- 'msbuild /t:Borepin_iOS /p:Configuration=Debug /p:Platform=iPhone /p:ArchiveOnBuild=true' # build the project /p:AndroidKeyStore=True
|
||||
artifacts:
|
||||
expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
|
||||
paths:
|
||||
- Borepin/Borepin.iOS/bin/iPhone/Debug/Borepin.ipa
|
||||
- Borepin/Borepin.iOS/bin/iPhone/Debug/Borepin.app.dSYM
|
||||
- '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
|
||||
|
||||
# test_job:
|
||||
# stage: test
|
||||
# tags:
|
||||
# - xamarin
|
||||
# - windows
|
||||
# # only:
|
||||
# # - tags
|
||||
# script:
|
||||
# - '& "$env:NUNIT_PATH" ".\$env:TEST_FOLDER\Tests.dll"' # running NUnit tests
|
||||
# artifacts:
|
||||
# when: always # save test results even when the task fails
|
||||
# expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
|
||||
# paths:
|
||||
# - '.\TestResult.xml' # saving NUnit results to copy to deploy folder
|
||||
# dependencies:
|
||||
# - build_job
|
||||
|
||||
# deploy_job:
|
||||
# stage: deploy
|
||||
# only:
|
||||
# - tags
|
||||
# script:
|
||||
# # Compose a folder for each release based on commit tag.
|
||||
# # Assuming your tag is Rev1.0.0.1, and your last commit message is 'First commit'
|
||||
# # the artifact files will be copied to:
|
||||
# # P:\Projects\YourApp\Builds\Rev1.0.0.1 - First commit\
|
||||
# - '$commitSubject = git log -1 --pretty=%s'
|
||||
# - '$deployFolder = $($env:DEPLOY_FOLDER) + "\" + $($env:CI_BUILD_TAG) + " - " + $commitSubject + "\"'
|
||||
|
||||
# # xcopy takes care of recursively creating required folders
|
||||
# - 'xcopy /y ".\$env:EXE_RELEASE_FOLDER\YourApp.exe" "$deployFolder"'
|
||||
# - 'xcopy /y ".\$env:MSI_RELEASE_FOLDER\YourApp Setup.msi" "$deployFolder"'
|
||||
# - 'xcopy /y ".\TestResult.xml" "$deployFolder"'
|
||||
# dependencies:
|
||||
# - build_job
|
||||
# - test_job
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "FabAccessAPI/schema"]
|
||||
path = FabAccessAPI/schema
|
||||
url = https://gitlab.com/fabinfra/fabaccess/fabaccess-api.git
|
||||
[submodule "external/SASL"]
|
||||
path = external/SASL
|
||||
url = https://github.com/kjkriegel/S22.Sasl.git
|
82
Borepin.sln
82
Borepin.sln
@ -15,9 +15,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Bore
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.macOS", "Borepin\Borepin.macOS\Borepin.macOS.csproj", "{3EC23FE7-395E-4BBC-B56B-9455354BDA34}"
|
||||
EndProject
|
||||
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{41EC0C17-B456-42AE-89F2-79DDB8ED9858}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{41EC0C17-B456-42AE-89F2-79DDB8ED9858}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC", "NFC\NFC.csproj", "{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "NFC\NFC.csproj", "{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FabAccessAPI", "FabAccessAPI\FabAccessAPI.csproj", "{3251FCE9-FEA3-4662-8BEB-636BE6732D48}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "S22.Sasl", "external\SASL\S22.Sasl.csproj", "{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FabAccessAPI_Test", "FabAccessAPI_Test\FabAccessAPI_Test.csproj", "{1C85978A-9FC0-4064-8399-FA2455C5EC2A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -275,6 +281,78 @@ Global
|
||||
{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3251FCE9-FEA3-4662-8BEB-636BE6732D48}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7FEC3D5E-C240-41B6-BBFA-895C4F4D45CA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{1C85978A-9FC0-4064-8399-FA2455C5EC2A}.Release|x64.ActiveCfg = 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.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -15,7 +15,7 @@
|
||||
<MtouchEnableSGenConc>true</MtouchEnableSGenConc>
|
||||
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
|
||||
<ProvisioningType>automatic</ProvisioningType>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<MtouchSdkVersion>13.2</MtouchSdkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -51,9 +51,10 @@
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<MtouchDebug>true</MtouchDebug>
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||
<MtouchLink>Full</MtouchLink>
|
||||
<MtouchLink>SdkOnly</MtouchLink>
|
||||
<MtouchInterpreter>-all</MtouchInterpreter>
|
||||
<MtouchExtraArgs>--optimize=experimental-xforms-product-type</MtouchExtraArgs>
|
||||
<CodesignProvision>iOS Team Provisioning Profile: org.fab-access.borepin</CodesignProvision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
|
||||
<DebugType>none</DebugType>
|
||||
@ -64,8 +65,8 @@
|
||||
<MtouchArch>ARM64</MtouchArch>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
|
||||
<CodesignProvision>Automatic:AppStore</CodesignProvision>
|
||||
<MtouchExtraArgs>--optimize=experimental-xforms-product-type</MtouchExtraArgs>
|
||||
<MtouchLink>Full</MtouchLink>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
|
||||
<AppExtensionDebugBundleId />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="MultilingualAppToolkit">
|
||||
<MultilingualAppToolkitVersion>4.0</MultilingualAppToolkitVersion>
|
||||
@ -23,6 +23,7 @@
|
||||
<PackageReference Include="Prism.DryIoc.Forms" Version="8.0.0.1909" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.8.0.1687" />
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.5.3.2" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Page\MachinesPage.xaml.cs">
|
||||
@ -83,4 +84,4 @@
|
||||
<Folder Include="Base\" />
|
||||
<Folder Include="Behaviour\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
165
FabAccessAPI/Auth.cs
Normal file
165
FabAccessAPI/Auth.cs
Normal file
@ -0,0 +1,165 @@
|
||||
using Capnp;
|
||||
using FabAccessAPI.Schema;
|
||||
using S22.Sasl;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Exception = System.Exception;
|
||||
|
||||
namespace FabAccessAPI {
|
||||
/// Authentication Identity
|
||||
///
|
||||
/// Under the hood a string because the form depends heavily on the method
|
||||
public struct AuthCId {
|
||||
public string Id { get; private set; }
|
||||
|
||||
public AuthCId(string id) : this() { Id = id; }
|
||||
}
|
||||
|
||||
/// Authorization Identity
|
||||
///
|
||||
/// This identity is internal to FabAccess and completely independent from the authentication
|
||||
/// method or source
|
||||
public struct AuthZId {
|
||||
/// Main User ID. Generally an user name or similar
|
||||
public string Uid;
|
||||
|
||||
/// Sub user ID.
|
||||
///
|
||||
/// Can change scopes for permissions, e.g. having a +admin account with more permissions than
|
||||
/// the default account and +dashboard et.al. accounts that have restricted permissions for
|
||||
/// their applications
|
||||
public string Subuid;
|
||||
|
||||
/// Realm this account originates.
|
||||
///
|
||||
/// The Realm is usually described by a domain name but local policy may dictate an unrelated
|
||||
/// mapping
|
||||
public string Realm;
|
||||
}
|
||||
|
||||
/// Authentication/Authorization user object.
|
||||
///
|
||||
/// This struct contains the user as is passed to the actual authentication/authorization
|
||||
/// subsystems
|
||||
///
|
||||
public struct AuthUser {
|
||||
/// Contains the Authentication ID used
|
||||
///
|
||||
/// The authentication ID is an identifier for the authentication exchange. This is different
|
||||
/// than the ID of the user to be authenticated; for example when using x509 the authcid is
|
||||
/// the dn of the certificate, when using GSSAPI the authcid is of form `<userid>@<REALM>`
|
||||
public AuthCId Authcid;
|
||||
|
||||
/// Contains the Authorization ID
|
||||
///
|
||||
/// This is the identifier of the user to *authenticate as*. This in several cases is different
|
||||
/// to the `authcid`:
|
||||
/// If somebody wants to authenticate as somebody else, su-style.
|
||||
/// If a person wants to authenticate as a higher-permissions account, e.g. foo may set authzid foo+admin
|
||||
/// to split normal user and "admin" accounts.
|
||||
/// If a method requires a specific authcid that is different from the identifier of the user
|
||||
/// to authenticate as, e.g. GSSAPI, x509 client certificates, API TOKEN authentication.
|
||||
public AuthZId Authzid;
|
||||
|
||||
/// Contains the authentication method used
|
||||
///
|
||||
/// For the most part this is the SASL method
|
||||
public string AuthMethod;
|
||||
|
||||
/// Method-specific key-value pairs
|
||||
///
|
||||
/// Each method can use their own key-value pairs.
|
||||
/// E.g. EXTERNAL encodes the actual method used (x509 client certs, UID/GID for unix sockets,
|
||||
/// ...)
|
||||
public Dictionary<string, string> Kvs;
|
||||
|
||||
}
|
||||
|
||||
// Authentication has two parts: Granting the authentication itself and then performing the
|
||||
// authentication.
|
||||
// Granting the authentication checks if
|
||||
// a) the given authcid fits with the given (authMethod, kvs). In general a failure here indicates
|
||||
// a programming failure — the authcid come from the same source as that tuple
|
||||
// b) the given authcid may authenticate as the given authzid. E.g. if a given client certificate
|
||||
// has been configured for that user, if a GSSAPI user maps to a given user,
|
||||
public enum AuthError {
|
||||
/// Authentication ID is bad/unknown/..
|
||||
BadAuthcid,
|
||||
/// Authorization ID is unknown/..
|
||||
BadAuthzid,
|
||||
/// Authorization ID is not of form user+uid@realm
|
||||
MalformedAuthzid,
|
||||
/// User may not use that authorization id
|
||||
NotAllowedAuthzid,
|
||||
|
||||
}
|
||||
|
||||
public class UnauthorizedException : Exception{}
|
||||
public class UnsupportedMechanismException : Exception{}
|
||||
|
||||
/// <summary>
|
||||
/// THIS IS VERY INCOMPLETE!
|
||||
/// </summary>
|
||||
public class Auth {
|
||||
#region Log
|
||||
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
|
||||
private IAuthentication _authCap;
|
||||
public Auth(IAuthentication authCap) {
|
||||
_authCap = authCap;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetMechanisms() {
|
||||
return _authCap.Mechanisms();
|
||||
}
|
||||
|
||||
public async Task<bool> Authenticate(string mech, Dictionary<string, object> properties) {
|
||||
|
||||
var m = SaslFactory.Create(mech);
|
||||
foreach (KeyValuePair<string, object> entry in properties) {
|
||||
m.Properties.Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
var initialResponse = new Request.initialResponse();
|
||||
if (m.HasInitial) {
|
||||
initialResponse.Initial = m.GetResponse(new byte[0]);
|
||||
}
|
||||
|
||||
var req = new Request {
|
||||
Mechanism = m.Name,
|
||||
InitialResponse = initialResponse
|
||||
};
|
||||
|
||||
var resp = await _authCap.Start(req);
|
||||
while (!m.IsCompleted) {
|
||||
if (resp.which == Response.WHICH.Challence) {
|
||||
var additional = m.GetResponse(resp.Challence.ToArray());
|
||||
resp = await _authCap.Step(additional);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (resp.which == Response.WHICH.Outcome) {
|
||||
if (resp.Outcome.Result == Response.Result.successful) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
//TODO: Provide meaningful info about auth failure
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
64
FabAccessAPI/Connection.cs
Normal file
64
FabAccessAPI/Connection.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using Capnp.Rpc;
|
||||
using FabAccessAPI.Schema;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI {
|
||||
public class Connection {
|
||||
#region private variables
|
||||
private TcpRpcClient? _rpcClient = null;
|
||||
private IBootstrap? _bootstrapCap = null;
|
||||
private AuthUser? _authUser = null;
|
||||
private Auth? _auth = null;
|
||||
private Machines? _machines = null;
|
||||
#endregion
|
||||
|
||||
public TcpRpcClient? RpcClient => _rpcClient;
|
||||
|
||||
#region Log
|
||||
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="rpcClient">Should be an already configured and connected TcpRpcClient</param>
|
||||
public Connection(TcpRpcClient rpcClient) {
|
||||
_rpcClient = rpcClient;
|
||||
_bootstrapCap = _rpcClient.GetMain<IBootstrap>();
|
||||
_Log.Debug($"Done bootstraping API connection.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticate this connection.
|
||||
/// Calling this more then once is UB
|
||||
/// </summary>
|
||||
/// <param name="mech">The desired authentication mechanism</param>
|
||||
/// <param name="kvs">Key-Value data specific to the mechanism</param>
|
||||
/// <returns></returns>
|
||||
public async Task Auth(string mech, Dictionary<string, object> kvs) {
|
||||
// _bootstrapCap = await _bootstrapCap.Unwrap();
|
||||
var authCap = await _bootstrapCap.Auth();
|
||||
_auth = new Auth(authCap);
|
||||
var mechs = await _auth.GetMechanisms().ConfigureAwait(false);
|
||||
_Log.Debug($"The Server supports the following auth mechs: {string.Join(", ", mechs)}");
|
||||
|
||||
if (!mechs.Contains(mech)) {
|
||||
throw new UnsupportedMechanismException();
|
||||
}
|
||||
|
||||
await _auth.Authenticate(mech, kvs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a wrapped capability to interact with machines
|
||||
/// </summary>
|
||||
/// <returns>A wrapped capability to interact with machines</returns>
|
||||
public async Task<Machines> AccessMachines() {
|
||||
_machines ??= new Machines((await _bootstrapCap.Machines().ConfigureAwait(false)));
|
||||
return _machines;
|
||||
}
|
||||
}
|
||||
}
|
20
FabAccessAPI/FabAccessAPI.csproj
Normal file
20
FabAccessAPI/FabAccessAPI.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>8</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Capnp.Net.Runtime" Version="1.3.118" />
|
||||
<PackageReference Include="CapnpC.CSharp.MsBuild.Generation" Version="1.3.118" />
|
||||
<PackageReference Include="log4net" Version="2.0.12" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\external\SASL\S22.Sasl.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
204
FabAccessAPI/Machines.cs
Normal file
204
FabAccessAPI/Machines.cs
Normal file
@ -0,0 +1,204 @@
|
||||
using FabAccessAPI.Schema;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FabAccessAPI {
|
||||
|
||||
public class MachineException : Exception { }
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a capability for accessing the Machines subsystem of BFFH
|
||||
/// </summary>
|
||||
public class Machines {
|
||||
#region Log
|
||||
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
|
||||
|
||||
private IMachines _machinesCap;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Wrapper Class from a given capability.
|
||||
/// </summary>
|
||||
/// <param name="machinesCap">The capability that should be wrapped.</param>
|
||||
public Machines(IMachines machinesCap) {
|
||||
_machinesCap = machinesCap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all machines that BFFH knows about the user has been granted at least read access on
|
||||
/// </summary>
|
||||
/// <returns>ReadOnlyList of available Machines</returns>
|
||||
public async Task<IReadOnlyList<Machine>?> ListMachines() {
|
||||
return (await _machinesCap.ListMachines().ConfigureAwait(false)).Select(x => new Machine(x)) as IReadOnlyList<Machine>;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access a particular machine by known name. This may fail for two reasons:
|
||||
/// The user has not been granted access to know the machine exists or the machine does in fact not exist.
|
||||
/// In both cases the `machine` result will be a NULL-pointer
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the Machine</param>
|
||||
/// <returns>The Machine we requested</returns>
|
||||
public async Task<Machine> GetMachine(string name) {
|
||||
var mach = (await _machinesCap.GetMachine(name).ConfigureAwait(false)).Item1;
|
||||
if (mach == null) {
|
||||
//TODO: Throw a more specific exception!
|
||||
throw new MachineException();
|
||||
}
|
||||
return new Machine(mach);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A machine. This represents a machine as BFFH thinks about it which may mean
|
||||
///several machines or just part of a machine in the real world.
|
||||
///By itself this struct is completely useless since it contains only the information
|
||||
///that the machine exists the user is allowed to know about that fact. For all further
|
||||
///information the user has to call the contained capabilities which depending on the
|
||||
///access level may not be set. For example an admin will have every capability here
|
||||
///set but a simple user may only have `read` and `write` set while some users may not
|
||||
/// even have `read` set and are unable to even see if the machine is currently in use.
|
||||
/// </summary>
|
||||
public class Machine {
|
||||
private Schema.Machine _machine;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the Wrapper Class from a given capability
|
||||
/// </summary>
|
||||
/// <param name="machine">The capability that should be wrapped.</param>
|
||||
public Machine(Schema.Machine machine) {
|
||||
_machine = machine;
|
||||
}
|
||||
|
||||
// read operations
|
||||
|
||||
/// <summary>
|
||||
/// Get the MInfo Struct for the Machine.
|
||||
/// This contains everything BFFH knows about the Machine.
|
||||
/// </summary>
|
||||
/// <exception cref="UnauthorizedException"></exception>
|
||||
/// <returns>The MInfo Struct describing the Machine</returns>
|
||||
public async Task<Schema.Machine.MInfo> GetMInfo() {
|
||||
var readCap = _machine.Read;
|
||||
if (readCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
return (await _machine.Read.Info().ConfigureAwait(false)).Item1;
|
||||
}
|
||||
|
||||
//write operations
|
||||
|
||||
/// <summary>
|
||||
/// Try to use a machine. Throws a UnauthorizedException if the user does not have the required
|
||||
/// permissions to use this machine.
|
||||
///
|
||||
/// Use the Ret() Method of the returned Object to return the machine
|
||||
/// </summary>
|
||||
/// <exception cref="UnauthorizedException"></exception>
|
||||
/// <returns>Capability to give back the machine</returns>
|
||||
public Task<Schema.Machine.WriteInterface.IGiveBack> Use() {
|
||||
var writeCap = _machine.Write;
|
||||
if (writeCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
return writeCap.Use();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to reserve a machine. Throws a UnauthorizedException if the user does not have the required
|
||||
/// permissions to use this machine.
|
||||
///
|
||||
/// Use the Ret() Method of the returned Object to return the machine
|
||||
/// Use the Use() Nethod of the Machine to use your reserved machine.
|
||||
/// </summary>
|
||||
/// <exception cref="UnauthorizedException"></exception>
|
||||
/// <returns>Capability to give back the machine</returns>
|
||||
public Task<Schema.Machine.WriteInterface.IGiveBack> Reserve()
|
||||
{
|
||||
var writeCap = _machine.Write;
|
||||
if (writeCap == null)
|
||||
{
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
return writeCap.Reserve();
|
||||
}
|
||||
|
||||
|
||||
// public void GiveBack(Schema.Machine.WriteInterface.IGiveBack cap) {
|
||||
// cap.Ret();
|
||||
// }
|
||||
|
||||
//manage operations
|
||||
|
||||
/// <summary>
|
||||
/// After a machine has been used by an user with low enough permissions it's
|
||||
/// in the 'toCheck' state. This call then allows more priviledged users to
|
||||
/// "check" the machine and move it to the `free` state.
|
||||
///
|
||||
/// Calling this method signifies that the machine was checked and in an acceptable state.
|
||||
/// </summary>
|
||||
public async void MarkOk() {
|
||||
var manageCap = _machine.Manage;
|
||||
if (manageCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
// TODO: Do we really want to check this here?
|
||||
if ((await GetMInfo().ConfigureAwait(false)).State == State.toCheck) {
|
||||
await _machine.Manage.Ok().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// After a machine has been used by an user with low enough permissions it's
|
||||
/// in the 'toCheck' state. This call then allows more priviledged users to
|
||||
/// "check" the machine and move it to the `free` state.
|
||||
///
|
||||
/// Calling this method signifies that the machine was checked and in an unacceptable state.
|
||||
/// It will most likely be marked as `blocked` and the previous user will somehow be informed.
|
||||
/// </summary>
|
||||
public async void MarkNotOk() {
|
||||
var manageCap = _machine.Manage;
|
||||
if (manageCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
// TODO: Do we really want to check this here?
|
||||
if ((await GetMInfo().ConfigureAwait(false)).State == State.toCheck) {
|
||||
await _machine.Manage.NotOk().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
//administrative operations
|
||||
|
||||
/// <summary>
|
||||
/// Forcefully set a machine state.
|
||||
/// </summary>
|
||||
/// <param name="state">The desired machine state.</param>
|
||||
public async void ForceSetState(State state) {
|
||||
var adminCap = _machine.Admin;
|
||||
if (adminCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
await adminCap.ForceSetState(state).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the given user as current responsible
|
||||
/// </summary>
|
||||
/// <param name="user">The user</param>
|
||||
public async void ForceSetUser(String user) {
|
||||
var adminCap = _machine.Admin;
|
||||
if (adminCap == null) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
await adminCap.ForceSetUser(user).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
13
FabAccessAPI/Permissions.cs
Normal file
13
FabAccessAPI/Permissions.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
|
||||
//This is where the permissions subsystem will live
|
||||
namespace FabAccessAPI {
|
||||
public class Permissions {
|
||||
#region Log
|
||||
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
}
|
||||
}
|
1
FabAccessAPI/schema
Submodule
1
FabAccessAPI/schema
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4adb05341763b96a43440a6a96e0d9959ba71e89
|
67
FabAccessAPI_Test/FabAccessAPITests.cs
Normal file
67
FabAccessAPI_Test/FabAccessAPITests.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using FabAccessAPI;
|
||||
using Capnp;
|
||||
using Capnp.Rpc;
|
||||
using log4net.Config;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FabAccessAPI_Test {
|
||||
public class Tests {
|
||||
#region Log
|
||||
private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
|
||||
private static ILoggerFactory _loggerFactory;
|
||||
private Connection _connection;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void InitialSetup() {
|
||||
XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config"));
|
||||
_loggerFactory = LoggerFactory.Create(builder => {
|
||||
builder
|
||||
.AddFilter("Microsoft", LogLevel.Warning)
|
||||
.AddFilter("System", LogLevel.Warning);
|
||||
});
|
||||
_loggerFactory.AddLog4Net();
|
||||
Logging.LoggerFactory = _loggerFactory;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
var rpcClient = new TcpRpcClient();
|
||||
rpcClient.Connect("127.0.0.1", 59661);
|
||||
_connection = new Connection(rpcClient);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown() {
|
||||
_connection.RpcClient?.Dispose();
|
||||
_connection = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Connect() {
|
||||
Assert.AreEqual(ConnectionState.Active, _connection.RpcClient.State);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Authenticate() {
|
||||
await _connection.Auth("PLAIN", new Dictionary<string, object>{{"Username", "Testuser"}, {"Password", "secret"}});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Machines() {
|
||||
await _connection.Auth("PLAIN", new Dictionary<string, object>{{"Username", "Testuser"}, {"Password", "secret"}});
|
||||
var machines = await _connection.AccessMachines();
|
||||
|
||||
var testmachine = await machines.GetMachine("Testmachine");
|
||||
Assert.NotNull(testmachine);
|
||||
var minfo = await testmachine.GetMInfo();
|
||||
Assert.NotNull(minfo);
|
||||
_Log.Info($"Name: {minfo.Name}, Description: {minfo.Description}, State: {minfo.State.ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
26
FabAccessAPI_Test/FabAccessAPI_Test.csproj
Normal file
26
FabAccessAPI_Test/FabAccessAPI_Test.csproj
Normal file
@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="5.0.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FabAccessAPI\FabAccessAPI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="log4net.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
16
FabAccessAPI_Test/log4net.config
Normal file
16
FabAccessAPI_Test/log4net.config
Normal file
@ -0,0 +1,16 @@
|
||||
<log4net>
|
||||
<!-- A1 is set to be a ConsoleAppender -->
|
||||
<appender name="A1" type="log4net.Appender.ConsoleAppender">
|
||||
|
||||
<!-- A1 uses PatternLayout -->
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- Set root logger level to DEBUG and its only appender to A1 -->
|
||||
<root>
|
||||
<level value="ALL" />
|
||||
<appender-ref ref="A1" />
|
||||
</root>
|
||||
</log4net>
|
12
README.md
12
README.md
@ -11,6 +11,14 @@ Borepin
|
||||
* with .NET Desktop
|
||||
2. Install GTKSharp for Windows
|
||||
[download GTKSharp](https://www.mono-project.com/download/stable/#download-win)
|
||||
3. Install capnproto
|
||||
|
||||
3.1 If you have Chocolatey installed
|
||||
```shell
|
||||
$ choco install capnproto
|
||||
```
|
||||
3.2 else you can download it from [here](https://capnproto.org/install.html) and add it to your PATH
|
||||
|
||||
4. Clone Borepin
|
||||
[download Borepin](https://gitlab.com/fabinfra/fabaccess/client)
|
||||
6. Load Borepin
|
||||
@ -22,11 +30,11 @@ If Step 5. Build Borepin is failing because of GTKSharp, it could help to restar
|
||||
1. Install mono, gtk-sharp, msbuild, nuget
|
||||
1.1 Debian based
|
||||
```shell
|
||||
$ apt install mono-complete, gtk-sharp2, nuget
|
||||
$ apt install mono-complete, gtk-sharp2, nuget, capnproto
|
||||
```
|
||||
1.2 ArchLinux based
|
||||
```shell
|
||||
$ pacman -S mono, mono-msbuild, gtk-sharp-2, nuget
|
||||
$ pacman -S mono, mono-msbuild, gtk-sharp-2, nuget, capnproto
|
||||
```
|
||||
2. Clone Borepin
|
||||
```shell
|
||||
|
1
external/SASL
vendored
Submodule
1
external/SASL
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cb9a9919c971e00c52732fba983e82d795fbe4ad
|
Loading…
x
Reference in New Issue
Block a user