Initial Commit

This commit is contained in:
Mike Phares 2023-06-01 12:48:01 -07:00
commit 1f5deedc73
35 changed files with 2262 additions and 0 deletions

247
.editorconfig Normal file
View File

@ -0,0 +1,247 @@
[*.cs]
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_prefer_braces = false
csharp_prefer_simple_default_expression = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
csharp_style_conditional_delegate_call = true
csharp_style_deconstructed_variable_declaration = false
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = when_on_single_line:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = when_on_single_line:warning
csharp_style_expression_bodied_methods = when_on_single_line:warning
csharp_style_expression_bodied_operators = when_on_single_line:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_inlined_variable_declaration = false
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_pattern_local_over_anonymous_function = true:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_range_operator = true:warning
csharp_style_prefer_switch_expression = true:warning
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
csharp_style_var_elsewhere = false:warning
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_when_type_is_apparent = false:warning
csharp_using_directive_placement = outside_namespace
dotnet_code_quality_unused_parameters = all
dotnet_code_quality_unused_parameters = non_public # IDE0060: Remove unused parameter
dotnet_code_quality.CAXXXX.api_surface = private, internal
dotnet_diagnostic.CA1825.severity = warning # CA1823: Avoid zero-length array allocations
dotnet_diagnostic.CA1829.severity = warning # CA1829: Use Length/Count property instead of Count() when available
dotnet_diagnostic.CA1834.severity = warning # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)
dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed
dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049)
dotnet_diagnostic.IDE0060.severity = warning # IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0270.severity = warning # IDE0270: Null check can be simplified
dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method
dotnet_naming_rule.class_should_be_pascal_case.severity = warning
dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.class_should_be_pascal_case.symbols = class
dotnet_naming_rule.delegate_should_be_pascal_case.severity = warning
dotnet_naming_rule.delegate_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.delegate_should_be_pascal_case.symbols = delegate
dotnet_naming_rule.enum_should_be_pascal_case.severity = warning
dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum
dotnet_naming_rule.event_should_be_pascal_case.severity = warning
dotnet_naming_rule.event_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.event_should_be_pascal_case.symbols = event
dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.method_should_be_pascal_case.severity = warning
dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.method_should_be_pascal_case.symbols = method
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.private_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.private_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.private_method_should_be_pascal_case.symbols = private_method
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.symbols = private_or_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.symbols = private_or_internal_static_field
dotnet_naming_rule.property_should_be_pascal_case.severity = warning
dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.property_should_be_pascal_case.symbols = property
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.symbols = public_or_protected_field
dotnet_naming_rule.static_field_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field
dotnet_naming_rule.static_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_method_should_be_pascal_case.symbols = static_method
dotnet_naming_rule.struct_should_be_pascal_case.severity = warning
dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct
dotnet_naming_rule.types_should_be_pascal_case.severity = warning
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.private_of_internal_field.capitalization = pascal_case
dotnet_naming_style.private_of_internal_field.required_prefix = _
dotnet_naming_style.private_of_internal_field.required_suffix =
dotnet_naming_style.private_of_internal_field.word_separator =
dotnet_naming_symbols.abstract_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.abstract_method.applicable_kinds = method
dotnet_naming_symbols.abstract_method.required_modifiers = abstract
dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.class.applicable_kinds = class
dotnet_naming_symbols.class.required_modifiers =
dotnet_naming_symbols.delegate.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.delegate.applicable_kinds = delegate
dotnet_naming_symbols.delegate.required_modifiers =
dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enum.applicable_kinds = enum
dotnet_naming_symbols.enum.required_modifiers =
dotnet_naming_symbols.event.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.event.applicable_kinds = event
dotnet_naming_symbols.event.required_modifiers =
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.method.applicable_accessibilities = public
dotnet_naming_symbols.method.applicable_kinds = method
dotnet_naming_symbols.method.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.private_method.applicable_accessibilities = private
dotnet_naming_symbols.private_method.applicable_kinds = method
dotnet_naming_symbols.private_method.required_modifiers =
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_field.required_modifiers =
dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static
dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.property.applicable_kinds = property
dotnet_naming_symbols.property.required_modifiers =
dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected
dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field
dotnet_naming_symbols.public_or_protected_field.required_modifiers =
dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_field.applicable_kinds = field
dotnet_naming_symbols.static_field.required_modifiers = static
dotnet_naming_symbols.static_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_method.applicable_kinds = method
dotnet_naming_symbols.static_method.required_modifiers = static
dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.struct.applicable_kinds = struct
dotnet_naming_symbols.struct.required_modifiers =
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.required_modifiers =
dotnet_remove_unnecessary_suppression_exclusions = 0
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
dotnet_style_allow_statement_immediately_after_block_experimental = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true:warning
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false
dotnet_style_prefer_conditional_expression_over_return = false
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true
dotnet_style_qualification_for_event = false:error
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false:error
dotnet_style_qualification_for_property = false:error
dotnet_style_readonly_field = true:warning
dotnet_style_require_accessibility_modifiers = for_non_interface_members
end_of_line = crlf
file_header_template = unset
indent_size = 4
indent_style = space
insert_final_newline = false
root = true
tab_width = 4
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822
# https://github.com/dotnet/aspnetcore/blob/main/.editorconfig
# https://github.com/dotnet/project-system/blob/main/.editorconfig

343
.gitignore vendored Normal file
View File

@ -0,0 +1,343 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# **/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/thunder-tests/
# Libman.json
/wwwroot/lib/*

43
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,43 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (web) - Server",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "buildServer",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Server/bin/Debug/net7.0/Barcode.Host.Server.dll",
"args": [],
"cwd": "${workspaceFolder}/Server",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger/index.html"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Server/Views"
}
},
{
"name": ".NET Core Attach - Server",
"type": "coreclr",
"request": "attach",
"preLaunchTask": "watchServer",
"processName": "Barcode.Host.Server.exe"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"cSpell.enabled": false,
"files.exclude": {
"**/.git": false
},
"thunder-client.saveToWorkspace": true,
"thunder-client.workspaceRelativePath": ".vscode",
"coverage-gutters.coverageBaseDir": "../.vscode/TestResults/*"
}

170
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,170 @@
{
"version": "2.0.0",
"options": {
"env": {
"serverUserSecretsId": "02dce973-df1d-4325-962a-ed549af8d4c5"
}
},
"tasks": [
{
"label": "userSecretsInit",
"command": "dotnet",
"type": "process",
"args": [
"user-secrets",
"-p",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj",
"init"
],
"problemMatcher": "$msCompile"
},
{
"label": "userSecretsSet",
"command": "dotnet",
"type": "process",
"args": [
"user-secrets",
"-p",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj",
"set",
"asdf",
"123"
],
"problemMatcher": "$msCompile"
},
{
"label": "userSecretsMkLink",
"command": "cmd",
"type": "shell",
"args": [
"/c",
"mklink",
"/J",
".vscode\\UserSecrets",
"${userHome}\\AppData\\Roaming\\Microsoft\\UserSecrets\\$env:serverUserSecretsId"
],
"problemMatcher": "$msCompile"
},
{
"label": "buildServer",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publishServer",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "testDebug",
"command": "dotnet",
"type": "process",
"args": [
"test",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "testRelease",
"command": "dotnet",
"type": "process",
"args": [
"test",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
"-c",
"Release"
],
"problemMatcher": "$msCompile"
},
{
"label": "format",
"command": "dotnet",
"type": "process",
"args": [
"format",
"--report",
".vscode",
"--verbosity",
"detailed",
"--severity",
"warn"
],
"problemMatcher": "$msCompile"
},
{
"label": "old-watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj"
],
"problemMatcher": "$msCompile"
},
{
"label": "watchServer",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"--launch-profile",
"http",
"run",
"--project",
"${workspaceFolder}/Server/Barcode.Host.Server.csproj",
"--verbose"
],
"isBackground": true,
"dependsOn": [
"build"
],
"problemMatcher": {
"fileLocation": "relative",
"pattern": {
"regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
"file": 1,
"location": 2,
"severity": 3,
"code": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.*Shutdown requested.*",
"endsPattern": "^.*Application started.*"
}
}
},
{
"label": "PowerShell Force Clean",
"type": "shell",
"command": "& Get-ChildItem . -include bin,obj -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse }",
"problemMatcher": []
},
{
"label": "PowerShell Clean TestResults",
"type": "shell",
"command": "& Get-ChildItem . -include TestResults -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse }",
"problemMatcher": []
}
]
}

34
Barcode-Host.sln Normal file
View File

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Barcode.Host.Server.csproj", "{8D12E061-2AE3-4008-859A-1B5BEA41D553}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Barcode.Host.Shared.csproj", "{CBFA9393-988A-4D35-9B7F-BF4ABD355712}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server.Tests", "Server.Tests\Barcode.Host.Server.Tests.csproj", "{505C7449-F5BC-4A7A-8A89-4863C0258697}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8D12E061-2AE3-4008-859A-1B5BEA41D553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D12E061-2AE3-4008-859A-1B5BEA41D553}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D12E061-2AE3-4008-859A-1B5BEA41D553}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D12E061-2AE3-4008-859A-1B5BEA41D553}.Release|Any CPU.Build.0 = Release|Any CPU
{CBFA9393-988A-4D35-9B7F-BF4ABD355712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CBFA9393-988A-4D35-9B7F-BF4ABD355712}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CBFA9393-988A-4D35-9B7F-BF4ABD355712}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CBFA9393-988A-4D35-9B7F-BF4ABD355712}.Release|Any CPU.Build.0 = Release|Any CPU
{505C7449-F5BC-4A7A-8A89-4863C0258697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{505C7449-F5BC-4A7A-8A89-4863C0258697}.Debug|Any CPU.Build.0 = Debug|Any CPU
{505C7449-F5BC-4A7A-8A89-4863C0258697}.Release|Any CPU.ActiveCfg = Release|Any CPU
{505C7449-F5BC-4A7A-8A89-4863C0258697}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,53 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<VSTestLogger>trx</VSTestLogger>
<VSTestCollect>XPlat Code Coverage</VSTestCollect>
<VSTestResultsDirectory>../.vscode/TestResults</VSTestResultsDirectory>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Barcode.Host.Shared.csproj" />
<ProjectReference Include="..\Server\Barcode.Host.Server.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="..\Server\appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\Server\appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

5
Server.Tests/Class1.cs Normal file
View File

@ -0,0 +1,5 @@
namespace Server.Tests;
public class Class1
{
}

View File

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<UserSecretsId>02dce973-df1d-4325-962a-ed549af8d4c5</UserSecretsId>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Barcode.Host.Shared.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,33 @@
using System.Text.Json;
namespace Barcode.Host.Server.Models;
public record AppSettings(string ApiExportPath,
string ApiLoggingContentTypes,
string ApiLoggingPathPrefixes,
string ApiLogPath,
string ApiUrl,
string AttachmentPath,
string BuildNumber,
string Company,
string ConnectionString,
string GitCommitSeven,
string InboundApiAllowedIPList,
bool IsDevelopment,
bool IsStaging,
string MockRoot,
string MonAResource,
string MonASite,
string OI2SqlConnectionString,
string OIExportPath,
string URLs,
string WorkingDirectoryName)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,118 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace Barcode.Host.Server.Models.Binder;
public class AppSettings
{
#nullable disable
[Display(Name = "Api Export Path"), Required] public string ApiExportPath { get; set; }
[Display(Name = "Api Logging Content Types"), Required] public string ApiLoggingContentTypes { get; set; }
[Display(Name = "Api Logging Path Prefixes"), Required] public string ApiLoggingPathPrefixes { get; set; }
[Display(Name = "Api Log Path"), Required] public string ApiLogPath { get; set; }
[Display(Name = "Api URL"), Required] public string ApiUrl { get; set; }
[Display(Name = "Attachment Path"), Required] public string AttachmentPath { get; set; }
[Display(Name = "Build Number"), Required] public string BuildNumber { get; set; }
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "Is Development"), Required] public bool? IsDevelopment { get; set; }
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
[Display(Name = "Mock Root"), Required] public string MockRoot { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
[Display(Name = "OI Export Path"), Required] public string OIExportPath { get; set; }
[Display(Name = "URLs"), Required] public string URLs { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
#nullable restore
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
private static Models.AppSettings Get(AppSettings? appSettings)
{
Models.AppSettings result;
if (appSettings is null)
throw new NullReferenceException(nameof(appSettings));
if (appSettings.ApiExportPath is null)
throw new NullReferenceException(nameof(ApiExportPath));
if (appSettings.ApiLoggingContentTypes is null)
throw new NullReferenceException(nameof(ApiLoggingContentTypes));
if (appSettings.ApiLoggingPathPrefixes is null)
throw new NullReferenceException(nameof(ApiLoggingPathPrefixes));
if (appSettings.ApiLogPath is null)
throw new NullReferenceException(nameof(ApiLogPath));
if (appSettings.ApiUrl is null)
throw new NullReferenceException(nameof(ApiUrl));
if (appSettings.AttachmentPath is null)
throw new NullReferenceException(nameof(AttachmentPath));
if (appSettings.BuildNumber is null)
throw new NullReferenceException(nameof(BuildNumber));
if (appSettings.Company is null)
throw new NullReferenceException(nameof(Company));
if (appSettings.ConnectionString is null)
throw new NullReferenceException(nameof(ConnectionString));
if (appSettings.GitCommitSeven is null)
throw new NullReferenceException(nameof(GitCommitSeven));
if (appSettings.InboundApiAllowedIPList is null)
throw new NullReferenceException(nameof(InboundApiAllowedIPList));
if (appSettings.IsDevelopment is null)
throw new NullReferenceException(nameof(IsDevelopment));
if (appSettings.IsStaging is null)
throw new NullReferenceException(nameof(IsStaging));
if (appSettings.MockRoot is null)
throw new NullReferenceException(nameof(MockRoot));
if (appSettings.MonAResource is null)
throw new NullReferenceException(nameof(MonAResource));
if (appSettings.MonASite is null)
throw new NullReferenceException(nameof(MonASite));
if (appSettings.Oi2SqlConnectionString is null)
throw new NullReferenceException(nameof(Oi2SqlConnectionString));
if (appSettings.OIExportPath is null)
throw new NullReferenceException(nameof(OIExportPath));
if (appSettings.URLs is null)
throw new NullReferenceException(nameof(URLs));
if (appSettings.WorkingDirectoryName is null)
throw new NullReferenceException(nameof(WorkingDirectoryName));
result = new(
appSettings.ApiExportPath,
appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes,
appSettings.ApiLogPath,
appSettings.ApiUrl,
appSettings.AttachmentPath,
appSettings.BuildNumber,
appSettings.Company,
appSettings.ConnectionString,
appSettings.GitCommitSeven,
appSettings.InboundApiAllowedIPList,
appSettings.IsDevelopment.Value,
appSettings.IsStaging.Value,
appSettings.MockRoot,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
appSettings.OIExportPath,
appSettings.URLs,
appSettings.WorkingDirectoryName);
return result;
}
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
result = Get(appSettings);
return result;
}
}

106
Server/Program.cs Normal file
View File

@ -0,0 +1,106 @@
using Barcode.Host.Server.Models;
using Barcode.Host.Shared.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using System.Reflection;
namespace Barcode.Host.Server;
public class Program
{
private static (string, WebApplicationOptions) Get(string[] args)
{
Assembly assembly = Assembly.GetExecutingAssembly();
string? assemblyName = assembly.GetName()?.Name;
if (string.IsNullOrEmpty(assemblyName))
throw new Exception();
string baseAssemblyName = assemblyName.Split('.')[0];
string webRootPath = Path.Combine(AppContext.BaseDirectory.Split(baseAssemblyName)[0], baseAssemblyName, "wwwroot");
if (!Directory.Exists(webRootPath))
webRootPath = string.Empty;
WebApplicationOptions webApplicationOptions = new()
{
Args = args,
ContentRootPath = AppContext.BaseDirectory,
WebRootPath = webRootPath
};
return new(assemblyName, webApplicationOptions);
}
public static int Main(string[] args)
{
LoggerConfiguration loggerConfiguration = new();
(string assemblyName, WebApplicationOptions _) = Get(args);
WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
_ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assemblyName, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, webApplicationBuilder.Configuration);
_ = SerilogHostBuilderExtensions.UseSerilog(webApplicationBuilder.Host);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
try
{
_ = webApplicationBuilder.Services.AddMemoryCache();
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
_ = webApplicationBuilder.Services.AddControllersWithViews();
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
_ = webApplicationBuilder.Services.AddSwaggerGen();
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
{
sessionOptions.IdleTimeout = TimeSpan.FromSeconds(2000);
sessionOptions.Cookie.HttpOnly = true;
sessionOptions.Cookie.IsEssential = true;
}
);
WebApplication webApplication = webApplicationBuilder.Build();
_ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
if (!webApplicationBuilder.Environment.IsDevelopment())
{
_ = webApplication.UseExceptionHandler("/Error");
_ = webApplication.UseHttpsRedirection();
_ = webApplication.UseHsts();
}
else
{
if (string.IsNullOrEmpty(appSettings.URLs))
{
Environment.ExitCode = -1;
webApplication.Lifetime.StopApplication();
}
_ = webApplication.UseSwagger();
_ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
}
_ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
_ = SerilogApplicationBuilderExtensions.UseSerilogRequestLogging(webApplication);
_ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
_ = webApplication.UseStaticFiles();
_ = webApplication.UseSession();
_ = webApplication.MapControllers();
log.Information("Starting Web Application");
webApplication.Run();
return 0;
}
catch (Exception ex)
{
log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
}

View File

@ -0,0 +1,31 @@
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https-prod": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7130;http://localhost:5126",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
}
}
}
}

View File

@ -0,0 +1,47 @@
{
"ApiExportPath": "\\\\messdv002.na.infineon.com\\Candela",
"ApiUrl": "~/api",
"ConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Integrated Security=True;Initial Catalog=Metrology;",
"IsDevelopment": true,
"MockRoot": "",
"MonAResource": "OI_Metrology_Viewer_IFX",
"Oi2SqlConnectionString": "Data Source=MESSAD1001\\TEST1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"URLs": "https://localhost:7130;http://localhost:5126"
}

68
Server/appsettings.json Normal file
View File

@ -0,0 +1,68 @@
{
"AllowedHosts": "*",
"ApiExportPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si",
"ApiLoggingContentTypes": "application/json",
"ApiLoggingPathPrefixes": "/api/inbound",
"ApiUrl": "~/api",
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
"BuildNumber": "1",
"Company": "Infineon Technologies Americas Corp.",
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology;",
"GitCommitSeven": "1234567",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"InboundApiAllowedIPList": "",
"IsDevelopment": false,
"IsStaging": false,
"MockRoot": "",
"MonAResource": "OI_Metrology_Viewer_EC",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"URLs": "http://localhost:5002;",
"WorkingDirectoryName": "IFXApps"
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CliWrap" Version="3.6.3" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
namespace Barcode.Host.Shared.KeyboardMouse.Abstract;
public interface IAggregateInputReader
{
event InputReader.RaiseKeyPress OnKeyPress;
}

View File

@ -0,0 +1,72 @@
using Barcode.Host.Shared.KeyboardMouse.Abstract;
using Microsoft.Extensions.Logging;
namespace Barcode.Host.Shared.KeyboardMouse;
public class AggregateInputReader : IDisposable, IAggregateInputReader
{
private readonly ILogger<InputReader> _InputReaderLogger;
private Dictionary<string, InputReader>? _Readers = new();
public event InputReader.RaiseKeyPress? OnKeyPress;
public AggregateInputReader(ILogger<InputReader> inputReaderLogger)
{
_InputReaderLogger = inputReaderLogger;
System.Timers.Timer timer = new()
{
Interval = 10 * 1000,
Enabled = true
};
timer.Elapsed += (_, _) => Scan();
timer.Start();
}
private void ReaderOnOnKeyPress(KeyPressEvent e) => OnKeyPress?.Invoke(e);
private void Scan()
{
string[] files = Directory.GetFiles("/dev/input/", "event*");
foreach (string file in files)
{
if (_Readers is not null && _Readers.ContainsKey(file))
{
continue;
}
InputReader reader = new(file, _InputReaderLogger);
reader.OnKeyPress += ReaderOnOnKeyPress;
_Readers?.Add(file, reader);
}
IEnumerable<InputReader>? deadReaders = _Readers?.Values.Where(r => r.Faulted);
if (deadReaders is not null)
{
foreach (InputReader? dr in deadReaders)
{
_ = _Readers?.Remove(dr.Path);
dr.OnKeyPress -= ReaderOnOnKeyPress;
dr.Dispose();
}
}
}
public void Dispose()
{
if (_Readers is not null)
{
foreach (InputReader d in _Readers.Values)
{
d.OnKeyPress -= ReaderOnOnKeyPress;
d.Dispose();
}
}
_Readers = null;
}
}

View File

@ -0,0 +1,82 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public static class DeviceReader
{
public static IEnumerable<LinuxDevice> Get(string path = "/proc/bus/input/devices")
{
List<LinuxDevice> devices = new();
using FileStream filestream = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader reader = new(filestream);
LinuxDevice linuxDevice = new();
while (!reader.EndOfStream)
{
string? line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
if (!string.IsNullOrWhiteSpace(linuxDevice.Name))
{
devices.Add(linuxDevice);
linuxDevice = new LinuxDevice();
}
continue;
}
if (line.StartsWith("I"))
ApplyIdentifier(line, linuxDevice);
else if (line.StartsWith("N"))
linuxDevice.Name = line.Substring(9, line.Length - 9 - 1);
else if (line.StartsWith("P"))
linuxDevice.PhysicalPath = line[8..];
else if (line.StartsWith("S"))
linuxDevice.SysFsPath = line[9..];
else if (line.StartsWith("U"))
linuxDevice.UniqueIdentificationCode = line[8..];
else if (line.StartsWith("H"))
linuxDevice.Handlers = line[12..]
.Split(" ")
.Where(h => !string.IsNullOrWhiteSpace(h))
.ToList();
else if (line.StartsWith("B"))
linuxDevice.Bitmaps.Add(line[3..]);
}
return devices;
}
private static void ApplyIdentifier(string line, LinuxDevice linuxDevice)
{
string[] values = line[3..]
.Split(" ");
foreach (string v in values)
{
string[] kvp = v.Split("=");
switch (kvp[0])
{
case "Bus":
linuxDevice.Identifier.Bus = kvp[1];
break;
case "Vendor":
linuxDevice.Identifier.Vendor = kvp[1];
break;
case "Product":
linuxDevice.Identifier.Product = kvp[1];
break;
case "Version":
linuxDevice.Identifier.Version = kvp[1];
break;
}
}
}
}

View File

@ -0,0 +1,277 @@
namespace Barcode.Host.Shared.KeyboardMouse;
/// <summary>
/// Mapping for this can be found here: https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h
/// </summary>
public enum EventCode
{
Reserved = 0,
Esc = 1,
Num1 = 2,
Num2 = 3,
Num3 = 4,
Num4 = 5,
Num5 = 6,
Num6 = 7,
Num7 = 8,
Num8 = 9,
Num9 = 10,
Num0 = 11,
Minus = 12,
Equal = 13,
Backspace = 14,
Tab = 15,
Q = 16,
W = 17,
E = 18,
R = 19,
T = 20,
Y = 21,
U = 22,
I = 23,
O = 24,
P = 25,
LeftBrace = 26,
RightBrace = 27,
Enter = 28,
LeftCtrl = 29,
A = 30,
S = 31,
D = 32,
F = 33,
G = 34,
H = 35,
J = 36,
K = 37,
L = 38,
Semicolon = 39,
Apostrophe = 40,
Grave = 41,
LeftShift = 42,
Backslash = 43,
Z = 44,
X = 45,
C = 46,
V = 47,
B = 48,
N = 49,
M = 50,
Comma = 51,
Dot = 52,
Slash = 53,
RightShift = 54,
KpAsterisk = 55,
LeftAlt = 56,
Space = 57,
Capslock = 58,
F1 = 59,
Pf2 = 60,
F3 = 61,
F4 = 62,
F5 = 63,
F6 = 64,
F7 = 65,
F8 = 66,
Pf9 = 67,
F10 = 68,
Numlock = 69,
ScrollLock = 70,
Kp7 = 71,
Kp8 = 72,
Kp9 = 73,
PkpMinus = 74,
Kp4 = 75,
Kp5 = 76,
Kp6 = 77,
KpPlus = 78,
Kp1 = 79,
Kp2 = 80,
Kp3 = 81,
Kp0 = 82,
KpDot = 83,
Zenkakuhankaku = 85,
//102ND = 86,
F11 = 87,
F12 = 88,
Ro = 89,
Katakana = 90,
Hiragana = 91,
Henkan = 92,
Katakanahiragana = 93,
Muhenkan = 94,
KpJpComma = 95,
KpEnter = 96,
RightCtrl = 97,
KpSlash = 98,
SysRq = 99,
RightAlt = 100,
LineFeed = 101,
Home = 102,
Up = 103,
Pageup = 104,
Left = 105,
Right = 106,
End = 107,
Down = 108,
Pagedown = 109,
Insert = 110,
Delete = 111,
Macro = 112,
Mute = 113,
VolumeDown = 114,
VolumeUp = 115,
Power = 116, // SC System Power Down
KpEqual = 117,
KpPlusMinus = 118,
Pause = 119,
Scale = 120, // AL Compiz Scale (Expose)
KpComma = 121,
Hangeul = 122,
Hanja = 123,
Yen = 124,
LeftMeta = 125,
RightMeta = 126,
Compose = 127,
Stop = 128, // AC Stop
Again = 129,
Props = 130, // AC Properties
Undo = 131, // AC Undo
Front = 132,
Copy = 133, // AC Copy
Open = 134, // AC Open
Paste = 135, // AC Paste
Find = 136, // AC Search
Cut = 137, // AC Cut
Help = 138, // AL Integrated Help Center
Menu = 139, // Menu (show menu)
Calc = 140, // AL Calculator
Setup = 141,
Sleep = 142, // SC System Sleep
Wakeup = 143, // System Wake Up
File = 144, // AL Local Machine Browser
Sendfile = 145,
DeleteFile = 146,
Xfer = 147,
Prog1 = 148,
Prog2 = 149,
Www = 150, // AL Internet Browser
MsDos = 151,
Coffee = 152, // AL Terminal Lock/Screensaver
RotateDisplay = 153, // Display orientation for e.g. tablets
CycleWindows = 154,
Mail = 155,
Bookmarks = 156, // AC Bookmarks
Computer = 157,
Back = 158, // AC Back
Forward = 159, // AC Forward
CloseCd = 160,
EjectCd = 161,
EjectCloseCd = 162,
NextSong = 163,
PlayPause = 164,
PreviousSong = 165,
StopCd = 166,
Record = 167,
Rewind = 168,
Phone = 169, // Media Select Telephone
Iso = 170,
Config = 171, // AL Consumer Control Configuration
Homepage = 172, // AC Home
Refresh = 173, // AC Refresh
Exit = 174, // AC Exit
Move = 175,
Edit = 176,
ScrollUp = 177,
ScrollDown = 178,
KpLeftParen = 179,
KpRightParen = 180,
New = 181, // AC New
Redo = 182, // AC Redo/Repeat
F13 = 183,
F14 = 184,
F15 = 185,
F16 = 186,
F17 = 187,
F18 = 188,
F19 = 189,
F20 = 190,
F21 = 191,
F22 = 192,
F23 = 193,
F24 = 194,
PlayCd = 200,
PauseCd = 201,
Prog3 = 202,
Prog4 = 203,
Dashboard = 204, // AL Dashboard
Suspend = 205,
Close = 206, // AC Close
Play = 207,
FastForward = 208,
BassBoost = 209,
Print = 210, // AC Print
Hp = 211,
Camera = 212,
Sound = 213,
Question = 214,
Email = 215,
Chat = 216,
Search = 217,
Connect = 218,
Finance = 219, // AL Checkbook/Finance
Sport = 220,
Shop = 221,
AltErase = 222,
Cancel = 223, // AC Cancel
BrightnessDown = 224,
BrightnessUp = 225,
Media = 226,
SwitchVideoMode = 227, // Cycle between available video outputs (Monitor/LCD/TV-out/etc)
KbdIllumToggle = 228,
KbdIllumDown = 229,
KbdIllumUp = 230,
Send = 231, // AC Send
Reply = 232, // AC Reply
ForwardMail = 233, // AC Forward Msg
Save = 234, // AC Save
Documents = 235,
Battery = 236,
Bluetooth = 237,
Wlan = 238,
Uwb = 239,
Unknown = 240,
VideoNext = 241, // drive next video source
VideoPrev = 242, // drive previous video source
BrightnessCycle = 243, // brightness up, after max is min
BrightnessAuto = 244, // Set Auto Brightness: manual brightness control is off, rely on ambient
DisplayOff = 245, // display device to off state
Wwan = 246, // Wireless WAN (LTE, UMTS, GSM, etc.)
RfKill = 247, // Key that controls all radios
MicMute = 248, // Mute / unmute the microphone
LeftMouse = 272,
RightMouse = 273,
MiddleMouse = 274,
MouseBack = 275,
MouseForward = 276,
ToolFinger = 325,
ToolQuintTap = 328,
Touch = 330,
ToolDoubleTap = 333,
ToolTripleTap = 334,
ToolQuadTap = 335,
Mic = 582
}

View File

@ -0,0 +1,64 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public enum EventType
{
/// <summary>
/// Used as markers to separate events. Events may be separated in time or in space, such as with the multitouch protocol.
/// </summary>
EV_SYN,
/// <summary>
/// Used to describe state changes of keyboards, buttons, or other key-like devices.
/// </summary>
EV_KEY,
/// <summary>
/// Used to describe relative axis value changes, e.g. moving the mouse 5 units to the left.
/// </summary>
EV_REL,
/// <summary>
/// Used to describe absolute axis value changes, e.g. describing the coordinates of a touch on a touchscreen.
/// </summary>
EV_ABS,
/// <summary>
/// Used to describe miscellaneous input data that do not fit into other types.
/// </summary>
EV_MSC,
/// <summary>
/// Used to describe binary state input switches.
/// </summary>
EV_SW,
/// <summary>
/// Used to turn LEDs on devices on and off.
/// </summary>
EV_LED,
/// <summary>
/// Used to output sound to devices.
/// </summary>
EV_SND,
/// <summary>
/// Used for autorepeating devices.
/// </summary>
EV_REP,
/// <summary>
/// Used to send force feedback commands to an input device.
/// </summary>
EV_FF,
/// <summary>
/// A special type for power button and switch input.
/// </summary>
EV_PWR,
/// <summary>
/// Used to receive force feedback device status.
/// </summary>
EV_FF_STATUS,
}

View File

@ -0,0 +1,166 @@
using Microsoft.Extensions.Logging;
namespace Barcode.Host.Shared.KeyboardMouse;
public class InputReader : IDisposable
{
private readonly ILogger<InputReader> _Logger;
private const int _BufferLength = 24;
private static readonly int _PiOffset;
private readonly byte[] _Buffer = new byte[_BufferLength];
private FileStream? _Stream;
private bool _Disposing;
public delegate void RaiseKeyPress(KeyPressEvent e);
public delegate void RaiseMouseMove(MouseMoveEvent e);
public event RaiseKeyPress? OnKeyPress;
public event RaiseMouseMove? OnMouseMove;
public string Path { get; }
public bool Faulted { get; private set; }
static InputReader()
{
if (RunningOnRaspberryPi())
{
_PiOffset = -8;
}
}
public InputReader(
string path,
ILogger<InputReader> logger)
{
_Logger = logger;
Path = path;
try
{
_Stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
catch (UnauthorizedAccessException ex)
{
_Logger.LogError(ex, "Current user doesn't have permissions to access input data. Add user to input group to correct this error");
Faulted = true;
}
catch (IOException ex)
{
_Logger.LogWarning(ex, $"Error occurred while trying to build stream for {path}");
Faulted = true;
}
_ = Task.Run(Run);
}
private void Run()
{
while (true)
{
if (_Disposing)
break;
try
{
if (!Faulted && _Stream is not null)
{
_ = _Stream.Read(_Buffer, 0, _BufferLength);
}
}
catch (IOException ex)
{
_Logger.LogInformation(ex, $"Error occured while trying to read from the stream for {Path}");
Faulted = true;
}
EventType type = GetEventType();
short code = GetCode();
int value = GetValue();
switch (type)
{
case EventType.EV_KEY:
HandleKeyPressEvent(code, value);
break;
case EventType.EV_REL:
MouseAxis axis = (MouseAxis)code;
MouseMoveEvent e = new(axis, value);
OnMouseMove?.Invoke(e);
break;
}
}
}
private int GetValue()
{
byte[] valueBits = new[]
{
_Buffer[20 + _PiOffset],
_Buffer[21 + _PiOffset],
_Buffer[22 + _PiOffset],
_Buffer[23 + _PiOffset]
};
int value = BitConverter.ToInt32(valueBits, 0);
return value;
}
private short GetCode()
{
byte[] codeBits = new[]
{
_Buffer[18 + _PiOffset],
_Buffer[19 + _PiOffset]
};
short code = BitConverter.ToInt16(codeBits, 0);
return code;
}
private EventType GetEventType()
{
byte[] typeBits = new[]
{
_Buffer[16 + _PiOffset],
_Buffer[17 + _PiOffset]
};
short type = BitConverter.ToInt16(typeBits, 0);
EventType eventType = (EventType)type;
return eventType;
}
private void HandleKeyPressEvent(short code, int value)
{
EventCode c = (EventCode)code;
KeyState s = (KeyState)value;
KeyPressEvent e = new(c, s);
OnKeyPress?.Invoke(e);
}
public void Dispose()
{
_Disposing = true;
_Stream?.Dispose();
_Stream = null;
}
private static bool RunningOnRaspberryPi()
{
string path = "/proc/cpuinfo";
string[] text = File.ReadAllLines(path);
bool runningOnPi = text.Any(l => l.Contains("Raspberry Pi"));
return runningOnPi;
}
}

View File

@ -0,0 +1,14 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public readonly struct KeyPressEvent
{
public KeyPressEvent(EventCode code, KeyState state)
{
Code = code;
State = state;
}
public EventCode Code { get; }
public KeyState State { get; }
}

View File

@ -0,0 +1,8 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public enum KeyState
{
KeyUp,
KeyDown,
KeyHold
}

View File

@ -0,0 +1,18 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public class LinuxDevice
{
public LinuxDeviceIdentifier Identifier { get; set; } = new();
public string? Name { get; set; }
public string? PhysicalPath { get; set; }
public string? SysFsPath { get; set; }
public string? UniqueIdentificationCode { get; set; }
public List<string> Handlers { get; set; } = new();
public List<string> Bitmaps { get; set; } = new();
}

View File

@ -0,0 +1,12 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public class LinuxDeviceIdentifier
{
public string? Bus { get; set; }
public string? Vendor { get; set; }
public string? Product { get; set; }
public string? Version { get; set; }
}

View File

@ -0,0 +1,7 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public enum MouseAxis
{
X,
Y
}

View File

@ -0,0 +1,14 @@
namespace Barcode.Host.Shared.KeyboardMouse;
public readonly struct MouseMoveEvent
{
public MouseMoveEvent(MouseAxis axis, int amount)
{
Axis = axis;
Amount = amount;
}
public MouseAxis Axis { get; }
public int Amount { get; }
}

View File

@ -0,0 +1,44 @@
using CliWrap;
using CliWrap.Buffered;
namespace Barcode.Host.Shared.Linux;
public class LinuxGroupManager : ILinuxGroupManager
{
public async Task<bool> IsInInputGroup()
{
BufferedCommandResult result = await Cli.Wrap("id")
.ExecuteBufferedAsync();
string output = result.StandardOutput;
const StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries;
bool inInputGroup = output.Split(new[] { ' ' }, options)
.First(p => p.StartsWith("groups"))
.Remove(0, "groups".Length)
.Split(',', options)
.Any(p => p.Contains("input"));
return inInputGroup;
}
public async Task AddUserToInputGroup(string password)
{
using CancellationTokenSource cts = new();
cts.CancelAfter(TimeSpan.FromSeconds(10));
_ = await Cli.Wrap("bash")
.WithArguments($"-c \"echo '{password}' | sudo -S gpasswd -a $USER input")
.ExecuteBufferedAsync(cts.Token);
}
public async Task RebootSystem(string password)
{
using CancellationTokenSource cts = new();
cts.CancelAfter(TimeSpan.FromSeconds(10));
_ = await Cli.Wrap("bash")
.WithArguments($"-c \"echo '{password}' | sudo -S reboot\"")
.ExecuteBufferedAsync(cts.Token);
}
}

View File

@ -0,0 +1,10 @@
namespace Barcode.Host.Shared.Linux;
public interface ILinuxGroupManager
{
Task<bool> IsInInputGroup();
Task AddUserToInputGroup(string password);
Task RebootSystem(string password);
}

View File

@ -0,0 +1,9 @@
namespace Barcode.Host.Shared.Models;
public interface IWorkingDirectory
{
static string GetWorkingDirectory(string? executingAssemblyName, string subDirectoryName) =>
WorkingDirectory.GetWorkingDirectory(executingAssemblyName, subDirectoryName);
}

View File

@ -0,0 +1,15 @@
namespace Barcode.Host.Shared.Models.Stateless;
public interface IAppSettingsController<T>
{
enum Action : int
{
App = 0,
DevOps = 1
}
static string GetRouteName() => nameof(IAppSettingsController<T>)[1..^10];
T GetAppSettings();
}

View File

@ -0,0 +1,10 @@
namespace Barcode.Host.Shared.Models.Stateless;
public interface IAppSettingsRepository<T>
{
T GetAppSettings();
string GetBuildNumberAndGitCommitSeven();
void VerifyConnectionStrings();
}

View File

@ -0,0 +1,10 @@
using System.Runtime.CompilerServices;
namespace Barcode.Host.Shared.Models.Stateless;
public interface IMethodName
{
static string? GetActualAsyncMethodName([CallerMemberName] string? name = null) => name;
}

View File

@ -0,0 +1,50 @@
namespace Barcode.Host.Shared.Models;
internal abstract class WorkingDirectory
{
internal static string GetWorkingDirectory(string? executingAssemblyName, string subDirectoryName)
{
string result = string.Empty;
if (executingAssemblyName is null)
throw new Exception();
string traceFile;
List<string> directories = new();
Environment.SpecialFolder[] specialFolders = new Environment.SpecialFolder[]
{
Environment.SpecialFolder.LocalApplicationData,
Environment.SpecialFolder.ApplicationData,
Environment.SpecialFolder.History,
Environment.SpecialFolder.CommonApplicationData,
Environment.SpecialFolder.InternetCache
};
foreach (Environment.SpecialFolder specialFolder in specialFolders)
directories.Add(Path.Combine(Environment.GetFolderPath(specialFolder), subDirectoryName, executingAssemblyName));
foreach (string directory in directories)
{
for (int i = 1; i < 3; i++)
{
if (i == 1)
result = directory;
else
result = string.Concat("D", directory[1..]);
try
{
if (!Directory.Exists(result))
_ = Directory.CreateDirectory(result);
traceFile = string.Concat(result, @"\", DateTime.Now.Ticks, ".txt");
File.WriteAllText(traceFile, traceFile);
File.Delete(traceFile);
break;
}
catch (Exception) { result = string.Empty; }
}
if (!string.IsNullOrEmpty(result))
break;
}
if (string.IsNullOrEmpty(result))
throw new Exception("Unable to set working directory!");
return result;
}
}