Adding MaidBotApi
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
**/*.bat
|
||||||
|
**/*.log
|
||||||
|
**/*.md
|
||||||
|
**/*.yml
|
||||||
|
**/.dockerignore
|
||||||
|
**/.editorconfig
|
||||||
|
**/.git
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitignore
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/bin
|
||||||
|
**/dist
|
||||||
|
**/dockerfile
|
||||||
|
**/node_modules
|
||||||
|
**/obj
|
||||||
|
**/package-lock.json
|
||||||
@@ -0,0 +1,330 @@
|
|||||||
|
## 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/
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# .NET Core SDK
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy Projects
|
||||||
|
COPY LCU.Api.Internal.MaidBotApi/LCU.Api.Internal.MaidBotApi.csproj LCU.Api.Internal.MaidBotApi/
|
||||||
|
COPY LCU.Api.Internal.MaidBotLib/LCU.Api.Internal.MaidBotLib.csproj LCU.Api.Internal.MaidBotLib/
|
||||||
|
|
||||||
|
# Configure NuGet auth for the Azure DevOps feed during restore.
|
||||||
|
ARG PAT=bh2lq3jibktw67b2wdbqyfln7cd3je6lk52kijntpj43v6kimpgq
|
||||||
|
RUN mkdir -p /root/.nuget/NuGet && \
|
||||||
|
printf '%s\n' \
|
||||||
|
'<?xml version="1.0" encoding="utf-8"?>' \
|
||||||
|
'<configuration>' \
|
||||||
|
' <packageSources>' \
|
||||||
|
' <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />' \
|
||||||
|
' <add key="LCU-Internal" value="https://landmarkcu.pkgs.visualstudio.com/_packaging/LCU-Internal/nuget/v3/index.json" />' \
|
||||||
|
' </packageSources>' \
|
||||||
|
' <packageSourceCredentials>' \
|
||||||
|
' <LCU-Internal>' \
|
||||||
|
' <add key="Username" value="AzureDevOps" />' \
|
||||||
|
' <add key="ClearTextPassword" value="'"${PAT}"'" />' \
|
||||||
|
' </LCU-Internal>' \
|
||||||
|
' </packageSourceCredentials>' \
|
||||||
|
'</configuration>' \
|
||||||
|
> /root/.nuget/NuGet/NuGet.Config
|
||||||
|
RUN dotnet restore LCU.Api.Internal.MaidBotApi/LCU.Api.Internal.MaidBotApi.csproj
|
||||||
|
|
||||||
|
# Copy All Files
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM build AS test
|
||||||
|
LABEL test=true
|
||||||
|
RUN dotnet test -c Release --results-directory /testresults --logger "trx;LogFileName=test_results.trx" LCU.Api.Internal.MaidBotTests/LCU.Api.Internal.MaidBotTests.csproj
|
||||||
|
|
||||||
|
# .NET Core Publish
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish LCU.Api.Internal.MaidBotApi/LCU.Api.Internal.MaidBotApi.csproj -c Release -o /app/publish
|
||||||
|
|
||||||
|
# ASP.NET Core
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine3.20
|
||||||
|
RUN apk add --no-cache icu-libs && apk add --no-cache tzdata;
|
||||||
|
ENV TZ America/Chicago
|
||||||
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
||||||
|
ENV ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "LCU.Api.Internal.MaidBotApi.dll"]
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29905.134
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.MaidBotApi", "LCU.API.Internal.MaidBotApi\LCU.Api.Internal.MaidBotApi.csproj", "{1C92A326-91A3-4904-B3EF-B766E10E7191}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.MaidBotTests", "LCU.Api.Internal.MaidBotTests\LCU.Api.Internal.MaidBotTests.csproj", "{98503299-44F3-410A-B61F-36BC1706F132}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{1C92A326-91A3-4904-B3EF-B766E10E7191} = {1C92A326-91A3-4904-B3EF-B766E10E7191}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.MaidBotSeqApp", "LCU.Api.Internal.MaidBotSeqApp\LCU.Api.Internal.MaidBotSeqApp.csproj", "{4E8E9B2F-69AD-4326-BD7E-DC53372C2092}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.MaidBotLib", "LCU.Api.Internal.MaidBotLib\LCU.Api.Internal.MaidBotLib.csproj", "{6FE57F07-EFA9-4769-AE61-95C72787AA9D}"
|
||||||
|
EndProject
|
||||||
|
Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "LCU.Api.Internal.MaidBotSql", "LCU.Api.Internal.MaidBotSql\LCU.Api.Internal.MaidBotSql.sqlproj", "{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1C92A326-91A3-4904-B3EF-B766E10E7191}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{98503299-44F3-410A-B61F-36BC1706F132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{98503299-44F3-410A-B61F-36BC1706F132}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{98503299-44F3-410A-B61F-36BC1706F132}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{98503299-44F3-410A-B61F-36BC1706F132}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4E8E9B2F-69AD-4326-BD7E-DC53372C2092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4E8E9B2F-69AD-4326-BD7E-DC53372C2092}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4E8E9B2F-69AD-4326-BD7E-DC53372C2092}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4E8E9B2F-69AD-4326-BD7E-DC53372C2092}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6FE57F07-EFA9-4769-AE61-95C72787AA9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6FE57F07-EFA9-4769-AE61-95C72787AA9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6FE57F07-EFA9-4769-AE61-95C72787AA9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6FE57F07-EFA9-4769-AE61-95C72787AA9D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ECCE6677-A2F2-4694-964F-F91EBE7AAC00}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {56A51B7E-A90A-4BFF-85D1-19ECB769AF6A}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
namespace LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
|
||||||
|
public class ApiConfiguration
|
||||||
|
{
|
||||||
|
public string AppName { get; set; }
|
||||||
|
public string SeqUrl { get; set; }
|
||||||
|
public string SeqApiKey { get; set; }
|
||||||
|
public string NotificationsApiEmail { get; set; }
|
||||||
|
public string BatchSchedulerCron { get; set; }
|
||||||
|
public FeatureFlags FeatureFlags { get; set; }
|
||||||
|
public string[] CorsAllowedOrigins { get; set; }
|
||||||
|
public string LogEmailTemplate { get; set; }
|
||||||
|
public string LogEmailRowTemplate { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
|
||||||
|
public class FeatureFlags
|
||||||
|
{
|
||||||
|
public bool LoggingEventConsumer { get; set; }
|
||||||
|
public bool RunScheduler { get; set; }
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using MassTransit;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Consumers;
|
||||||
|
|
||||||
|
public class LoggingEventConsumer : IConsumer<EventLog>
|
||||||
|
{
|
||||||
|
private readonly IServiceScopeFactory _scopeFactory;
|
||||||
|
|
||||||
|
public LoggingEventConsumer(IServiceScopeFactory scopeFactory)
|
||||||
|
{
|
||||||
|
_scopeFactory = scopeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Consume(ConsumeContext<EventLog> context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
await Task.Run(async () => await scope.ServiceProvider.GetRequiredService<IEventLogService>().HandleIncomingEventLog(context.Message));
|
||||||
|
}
|
||||||
|
catch (ServiceException serviceException)
|
||||||
|
{
|
||||||
|
Log.Fatal(serviceException, $"Handle Incoming EventLog Failure. " +
|
||||||
|
$"The Handle Incoming EventLog is placed on LCU.MaidBot_error.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Fatal(exception, $"Unexpected Handle Incoming EventLog Failure. " +
|
||||||
|
$"The Handle Incoming EventLog is placed on LCU.MaidBot_error.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
namespace LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
|
public class EventLogController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IEventLogService _eventLogService;
|
||||||
|
|
||||||
|
public EventLogController(IEventLogService eventLogService)
|
||||||
|
{
|
||||||
|
_eventLogService = eventLogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
[ProducesResponseType(204)]
|
||||||
|
[ProducesResponseType(typeof(EventLog), 400)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<IActionResult> Get()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var results = await _eventLogService.GetAsync();
|
||||||
|
if (results == null || !results.Any())
|
||||||
|
{
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(results);
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete()]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public IActionResult DeleteMany([FromBody] List<EventLog> eventLogs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_eventLogService.DeleteMany(eventLogs);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Exceptions;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
namespace LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
|
public class LoggingMatrixController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ILoggingMatrixService _loggingMatrixService;
|
||||||
|
|
||||||
|
public LoggingMatrixController(ILoggingMatrixService loggingMatrixService)
|
||||||
|
{
|
||||||
|
_loggingMatrixService = loggingMatrixService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "GetAllLoggingMatrixes")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<LoggingMatrix>), 200)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult> Get()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _loggingMatrixService.GetAsync();
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(typeof(LoggingMatrix), 201)]
|
||||||
|
[ProducesResponseType(typeof(List<string>), 400)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<ActionResult> Post([FromBody] LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _loggingMatrixService.SaveAsync(loggingMatrix);
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
Log.Error($"Result is null could not create Logging Matrix");
|
||||||
|
return StatusCode((StatusCodes.Status400BadRequest), "Could not create Logging Matrix.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return StatusCode(StatusCodes.Status201Created, result);
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut]
|
||||||
|
[ProducesResponseType(typeof(LoggingMatrix), 200)]
|
||||||
|
[ProducesResponseType(400)]
|
||||||
|
[ProducesResponseType(404)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<IActionResult> Put([FromBody] LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (loggingMatrix.LoggingMatrixId <= 0)
|
||||||
|
{
|
||||||
|
return BadRequest("Invalid ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _loggingMatrixService.UpdateAsync(loggingMatrix);
|
||||||
|
|
||||||
|
if(result == null)
|
||||||
|
{
|
||||||
|
return NotFound($"The LoggingMatrix with LoggingMatrixId: {loggingMatrix.LoggingMatrixId} " +
|
||||||
|
"could not be found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
namespace LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
|
public class QueueEventLogController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IQueueEventLogService _queueEventLogService;
|
||||||
|
|
||||||
|
public QueueEventLogController(IQueueEventLogService queueEventLogService)
|
||||||
|
{
|
||||||
|
_queueEventLogService = queueEventLogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(202)]
|
||||||
|
[ProducesResponseType(typeof(List<string>), 400)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public async Task<IActionResult> Post([FromBody] EventLog EventLog)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _queueEventLogService.QueueEventLog(EventLog);
|
||||||
|
return Accepted();
|
||||||
|
}
|
||||||
|
catch (ServiceException exception)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError, exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Unexpected Exception");
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.EnvironmentView;
|
||||||
|
namespace LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
|
||||||
|
public class StatusController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IEnvironmentView _environmentView;
|
||||||
|
|
||||||
|
public StatusController(IEnvironmentView environmentView)
|
||||||
|
{
|
||||||
|
_environmentView = environmentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet()]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
[ProducesResponseType(500)]
|
||||||
|
public IActionResult Get()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Ok(_environmentView);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Failure to return status");
|
||||||
|
return StatusCode((int)System.Net.HttpStatusCode.InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Shared.Common.NotificationApiLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.DataAccesses;
|
||||||
|
|
||||||
|
public interface INotificationsApiDao
|
||||||
|
{
|
||||||
|
Task SendEmailRequest(EmailRequest emailRequest);
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
|
||||||
|
using LCU.Shared.Common.NotificationApiLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.DataAccesses;
|
||||||
|
|
||||||
|
public class NotificationsApiDao : INotificationsApiDao
|
||||||
|
{
|
||||||
|
private readonly ApiConfiguration _apiConfiguration;
|
||||||
|
private readonly IPostRequest _postRequest;
|
||||||
|
|
||||||
|
public NotificationsApiDao(ApiConfiguration apiConfiguration, IPostRequest postRequest)
|
||||||
|
{
|
||||||
|
_apiConfiguration = apiConfiguration;
|
||||||
|
_postRequest = postRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendEmailRequest(EmailRequest emailRequest)
|
||||||
|
{
|
||||||
|
await _postRequest.Async(new Uri(_apiConfiguration.NotificationsApiEmail), emailRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.EnvironmentView;
|
||||||
|
|
||||||
|
public class EnvironmentView : IEnvironmentView
|
||||||
|
{
|
||||||
|
public string Application => _env.ApplicationName;
|
||||||
|
public DateTime CurrentDate => DateTime.Now;
|
||||||
|
public string BuildVersion => AssembleBuildVersion();
|
||||||
|
public DateTime BuildDate => AssemblyBuildDate();
|
||||||
|
public string Environment => _env.EnvironmentName;
|
||||||
|
private readonly IWebHostEnvironment _env;
|
||||||
|
|
||||||
|
public EnvironmentView(IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
_env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTime AssemblyBuildDate()
|
||||||
|
{
|
||||||
|
//https://stackoverflow.com/a/804310/266594
|
||||||
|
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||||
|
System.IO.FileInfo fileInfo = new System.IO.FileInfo(assembly.Location);
|
||||||
|
DateTime lastModified = fileInfo.LastWriteTime;
|
||||||
|
|
||||||
|
return lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AssembleBuildVersion()
|
||||||
|
{
|
||||||
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
return version == null ? "-.-.-" : version.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.EnvironmentView
|
||||||
|
{
|
||||||
|
public interface IEnvironmentView
|
||||||
|
{
|
||||||
|
string Application { get; }
|
||||||
|
DateTime CurrentDate { get; }
|
||||||
|
string BuildVersion { get; }
|
||||||
|
DateTime BuildDate { get; }
|
||||||
|
string Environment { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Exceptions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If an entity cannot be found, that specific error can allow for a 404 or 400 with more detail to be
|
||||||
|
* returned. So specify that to the API layer.
|
||||||
|
*/
|
||||||
|
public class NotFoundException : ApplicationException
|
||||||
|
{
|
||||||
|
public NotFoundException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Exceptions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Do not want to expose database and related exceptions to the controllers / web layer.
|
||||||
|
* The lower layers log what happened for developers, then return a general error; unless
|
||||||
|
* a more specific error can be returned in a way to allow the client to act (such as NotFound).
|
||||||
|
*/
|
||||||
|
public class ServerErrorException : Exception
|
||||||
|
{
|
||||||
|
public ServerErrorException() : base("A server error occured, and a response could not be produced.") { }
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Serilog;
|
||||||
|
using NCrontab;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
namespace LCU.API.Internal.MaidBotApi.HostedService;
|
||||||
|
|
||||||
|
public class SchedulerHostedService : BackgroundService
|
||||||
|
{
|
||||||
|
private readonly ApiConfiguration _apiConfiguration;
|
||||||
|
private readonly IServiceScopeFactory _scopeFactory;
|
||||||
|
|
||||||
|
private readonly CrontabSchedule _schedule;
|
||||||
|
private DateTime _nextScheduleRun;
|
||||||
|
public const string DefaultScheduleCronPattern = "*/5 * * * *";
|
||||||
|
|
||||||
|
private CancellationToken _cancellationToken;
|
||||||
|
|
||||||
|
public SchedulerHostedService(IServiceScopeFactory scopeFactory,
|
||||||
|
ApiConfiguration apiConfiguration)
|
||||||
|
{
|
||||||
|
_scopeFactory = scopeFactory;
|
||||||
|
_apiConfiguration = apiConfiguration;
|
||||||
|
|
||||||
|
var cron = (_apiConfiguration?.BatchSchedulerCron) ?? DefaultScheduleCronPattern;
|
||||||
|
_schedule = CrontabSchedule.Parse(cron);
|
||||||
|
_nextScheduleRun = _schedule.GetNextOccurrence(DateTime.Now);
|
||||||
|
|
||||||
|
_cancellationToken = new CancellationToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Log.Information("MaidBot Scheduler Hosted Service is starting.");
|
||||||
|
_cancellationToken = cancellationToken;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (_apiConfiguration.FeatureFlags.RunScheduler && DateTime.Now > _nextScheduleRun)
|
||||||
|
{
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
await Task.Run(async () => await scope.ServiceProvider.GetRequiredService<ILogDistributionService>().HandleLogDistribution());
|
||||||
|
|
||||||
|
_nextScheduleRun = _schedule.GetNextOccurrence(DateTime.Now);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(5000, cancellationToken); //5 seconds delay
|
||||||
|
} while (!cancellationToken.IsCancellationRequested);
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException taskCanceledException) when (_cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Log.Information(taskCanceledException, "MaidBot Scheduler Hosted Service was shut down normally.");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Error trying to startup main thread for MaidBot Scheduler Hosted Service");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("MaidBot Scheduler Hosted Service is stopping.");
|
||||||
|
}
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||||
|
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||||
|
<FileVersion>1.0.0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DocumentationFile>..\LCU.API.Internal.MaidBotApi\LCU.Api.Internal.MaidBotApi.xml</DocumentationFile>
|
||||||
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DocumentationFile>..\LCU.API.Internal.MaidBotApi\LCU.Api.Internal.MaidBotApi.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="LCU.Library.Internal.Exceptions" Version="1.0.0" />
|
||||||
|
<PackageReference Include="LCU.Library.Internal.LcuHttpClient" Version="2.0.1" />
|
||||||
|
<PackageReference Include="LCU.Library.Internal.LcuMassTransit" Version="1.0.0" />
|
||||||
|
<PackageReference Include="LCU.Library.Internal.LcuMassTransitModels" Version="1.1.0" />
|
||||||
|
<PackageReference Include="LCU.Library.Internal.Logging" Version="2.1.0" />
|
||||||
|
<PackageReference Include="LCU.Shared.Common.NotificationApiLib" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.14" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
|
||||||
|
<PackageReference Include="ncrontab" Version="3.3.1" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LCU.Api.Internal.MaidBotLib\LCU.Api.Internal.MaidBotLib.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Templates\LogEmailRowTemplate.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Templates\LogEmailTemplate.html">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<doc>
|
||||||
|
<assembly>
|
||||||
|
<name>LCU.Api.Internal.MaidBotApi</name>
|
||||||
|
</assembly>
|
||||||
|
<members>
|
||||||
|
<member name="T:LCU.Api.Internal.MaidBotApi.Exceptions.NotFoundException">
|
||||||
|
If an entity cannot be found, that specific error can allow for a 404 or 400 with more detail to be
|
||||||
|
returned. So specify that to the API layer.
|
||||||
|
</member>
|
||||||
|
<member name="T:LCU.Api.Internal.MaidBotApi.Exceptions.ServerErrorException">
|
||||||
|
Do not want to expose database and related exceptions to the controllers / web layer.
|
||||||
|
The lower layers log what happened for developers, then return a general error; unless
|
||||||
|
a more specific error can be returned in a way to allow the client to act (such as NotFound).
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</doc>
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using MassTransit;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.API.Internal.MaidBotApi.HostedService;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.EnvironmentView;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using LCU.Library.Internal.LcuMassTransitModels;
|
||||||
|
using LCU.Library.Internal.LcuMassTransit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Consumers;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
using LCU.Library.Internal.Logging.Models;
|
||||||
|
using LCU.Library.Internal.Logging;
|
||||||
|
using LCU.Library.Internal.Logging.Middleware;
|
||||||
|
using LCU.Library.Internal.LcuHttpClient;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.DataAccesses;
|
||||||
|
namespace LCU.API.Internal.MaidBot;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var builder = BuildBuilder(args);
|
||||||
|
BuildServicesAndConfigurations(builder);
|
||||||
|
BuildAppAndRun(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WebApplicationBuilder BuildBuilder(string[] args)
|
||||||
|
{
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
builder.Host.UseSerilog();
|
||||||
|
builder.Configuration.AddJsonFile("/app/config/environment-appsettings/appsettings.json", optional: true, reloadOnChange: true);
|
||||||
|
builder.Configuration.AddJsonFile("/app/config/workload-appsettings/appsettings.json", optional: true, reloadOnChange: true);
|
||||||
|
builder.Configuration.AddJsonFile("/vault/secrets/maidbot-api-seq-api-key.json", optional: true, reloadOnChange: true);
|
||||||
|
builder.Configuration.AddJsonFile("/vault/secrets/maidbot-api-connection-configuration-password.json", optional: true, reloadOnChange: true);
|
||||||
|
builder.Configuration.AddJsonFile("/vault/secrets/maidbot-api-connection-configuration-username.json", optional: true, reloadOnChange: true);
|
||||||
|
builder.Configuration.AddJsonFile("/vault/secrets/maidbot-database-connection.json", optional: true, reloadOnChange: true);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BuildServicesAndConfigurations(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
var services = builder.Services;
|
||||||
|
var configuration = builder.Configuration;
|
||||||
|
services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
services.AddEndpointsApiExplorer();
|
||||||
|
services.AddSwaggerGen();
|
||||||
|
|
||||||
|
services.AddDbContext<AppDbContext>(options =>
|
||||||
|
{
|
||||||
|
options.UseSqlServer(configuration.GetSection("Connections").GetSection("SQL").GetSection("MaidBotDB").Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddHttpClient();
|
||||||
|
services.AddLCUHttpServices();
|
||||||
|
|
||||||
|
//Configurations
|
||||||
|
var apiConfiguration = new ApiConfiguration();
|
||||||
|
configuration.GetSection("Primary").Bind(apiConfiguration);
|
||||||
|
services.AddSingleton(apiConfiguration);
|
||||||
|
//debugging
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(apiConfiguration));
|
||||||
|
|
||||||
|
var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, configuration);
|
||||||
|
//debugging
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(connectionConfiguration));
|
||||||
|
|
||||||
|
var receiveEndpointConfiguration = new ReceiveEndpointConfiguration();
|
||||||
|
receiveEndpointConfiguration = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ReceiveEndpoint");
|
||||||
|
services.AddSingleton(receiveEndpointConfiguration);
|
||||||
|
//debugging
|
||||||
|
Console.WriteLine(JsonConvert.SerializeObject(receiveEndpointConfiguration));
|
||||||
|
|
||||||
|
//EnvironmentView
|
||||||
|
services.AddScoped<IEnvironmentView, EnvironmentView>();
|
||||||
|
|
||||||
|
var loggerConfiguration = new LoggingConfiguration(apiConfiguration.AppName,
|
||||||
|
apiConfiguration.SeqApiKey,
|
||||||
|
apiConfiguration.SeqUrl);
|
||||||
|
var lcuLogging = new LcuLogging(loggerConfiguration);
|
||||||
|
lcuLogging.UseLcuLogging();
|
||||||
|
|
||||||
|
services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy(MyAllowSpecificOrigins,
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.WithOrigins(
|
||||||
|
apiConfiguration.CorsAllowedOrigins
|
||||||
|
).AllowAnyHeader().AllowAnyMethod();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddMaidBotServices(ref services);
|
||||||
|
AddMaidBotLib(ref services);
|
||||||
|
AddMaidBotDataAccesses(ref services);
|
||||||
|
AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfiguration, apiConfiguration);
|
||||||
|
|
||||||
|
// The Hosted
|
||||||
|
services.AddHostedService<SchedulerHostedService>();
|
||||||
|
|
||||||
|
// Register the Swagger generator, defining 1 or more Swagger documents
|
||||||
|
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = $"{apiConfiguration.AppName}", Version = "v1" }); });
|
||||||
|
|
||||||
|
services.Configure<ApiBehaviorOptions>(options =>
|
||||||
|
{
|
||||||
|
options.SuppressModelStateInvalidFilter = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddMaidBotServices(ref IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<ILogDistributionService, LogDistributionService>();
|
||||||
|
services.AddScoped<IQueueEventLogService, QueueEventLogService>();
|
||||||
|
services.AddScoped<INotificationsApiService, NotificationsApiService>();
|
||||||
|
services.AddScoped<ILoggingMatrixService, LoggingMatrixService>();
|
||||||
|
services.AddScoped<IEventLogService, EventLogService>();
|
||||||
|
services.AddScoped<IDebugEventLogService, DebugEventLogService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddMaidBotLib(ref IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<ILoggingMatrixRepository, LoggingMatrixRepository>();
|
||||||
|
services.AddScoped<IEventLogRepository, EventLogRepository>();
|
||||||
|
services.AddScoped<IDebugEventLogRepository, DebugEventLogRepository>();
|
||||||
|
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddMaidBotDataAccesses(ref IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<INotificationsApiDao, NotificationsApiDao>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddMassTransitServices(ref IServiceCollection services,
|
||||||
|
ConnectionConfiguration connectionConfiguration,
|
||||||
|
ReceiveEndpointConfiguration receiveEndpointConfiguration,
|
||||||
|
ApiConfiguration apiConfiguration)
|
||||||
|
{
|
||||||
|
services.AddMassTransit(x =>
|
||||||
|
{
|
||||||
|
x.AddConsumer<LoggingEventConsumer>();
|
||||||
|
|
||||||
|
x.UsingRabbitMq((context, cfg) =>
|
||||||
|
{
|
||||||
|
cfg.Host(connectionConfiguration.HostUrl, "/", host =>
|
||||||
|
{
|
||||||
|
host.Username(connectionConfiguration.UserName);
|
||||||
|
host.Password(connectionConfiguration.Password);
|
||||||
|
});
|
||||||
|
cfg.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420));
|
||||||
|
|
||||||
|
if (apiConfiguration.FeatureFlags.LoggingEventConsumer)
|
||||||
|
{
|
||||||
|
cfg.ReceiveEndpoint(receiveEndpointConfiguration.ReceiveEndpoint, e =>
|
||||||
|
{
|
||||||
|
e.ConfigureConsumer<LoggingEventConsumer>(context);
|
||||||
|
e.SetQuorumQueue();
|
||||||
|
e.PrefetchCount = receiveEndpointConfiguration.PrefetchLimit;
|
||||||
|
e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
services.AddMassTransitHostedService();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BuildAppAndRun(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "LCU.Api.Internal.MaidBotApi v1"));
|
||||||
|
app.UseMiddleware<RequestResponseLoggingMiddleware>();
|
||||||
|
app.UseSerilogRequestLogging(options =>
|
||||||
|
{
|
||||||
|
options.EnrichDiagnosticContext = RequestResponseLoggingMiddleware.RequestDataParser.EnrichFromRequest;
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseCors(MyAllowSpecificOrigins);
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.MapControllers();
|
||||||
|
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
namespace LCU.API.Internal.MaidBot.Security
|
||||||
|
{
|
||||||
|
public class AzureActiveDirectoryOptions
|
||||||
|
{
|
||||||
|
public string ClientId { get; set; }
|
||||||
|
public string ClientSecret { get; set; }
|
||||||
|
public string Instance { get; set; }
|
||||||
|
public string Domain { get; set; }
|
||||||
|
public string TenantId { get; set; }
|
||||||
|
public string ValidAudience { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace LCU.API.Internal.MaidBot.Security
|
||||||
|
{
|
||||||
|
public static class AzureAdServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder)
|
||||||
|
=> builder.AddAzureAdBearer(_ => { });
|
||||||
|
|
||||||
|
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder, Action<AzureActiveDirectoryOptions> configureOptions)
|
||||||
|
{
|
||||||
|
builder.Services.Configure(configureOptions);
|
||||||
|
builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureAzureOptions>();
|
||||||
|
builder.AddJwtBearer();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConfigureAzureOptions : IConfigureNamedOptions<JwtBearerOptions>
|
||||||
|
{
|
||||||
|
private readonly AzureActiveDirectoryOptions _azureOptions;
|
||||||
|
|
||||||
|
public ConfigureAzureOptions(IOptions<AzureActiveDirectoryOptions> azureOptions)
|
||||||
|
{
|
||||||
|
_azureOptions = azureOptions.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(string name, JwtBearerOptions options)
|
||||||
|
{
|
||||||
|
options.Audience = _azureOptions.ClientId;
|
||||||
|
options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
|
||||||
|
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidAudience = _azureOptions.ValidAudience
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(JwtBearerOptions options)
|
||||||
|
{
|
||||||
|
Configure(Options.DefaultName, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Exceptions;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class DebugEventLogService : IDebugEventLogService
|
||||||
|
{
|
||||||
|
private readonly IDebugEventLogRepository _debugEventLogRepository;
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
|
||||||
|
public DebugEventLogService(IUnitOfWork unitOfWork,
|
||||||
|
IDebugEventLogRepository debugEventLogRepository)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_debugEventLogRepository = debugEventLogRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DebugEventLog(EventLog eventLog)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(eventLog.DebugData))
|
||||||
|
{
|
||||||
|
var debugEventLog = new DebugEventLog(eventLog);
|
||||||
|
await SaveAsync(debugEventLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DebugEventLog> SaveAsync(DebugEventLog debugEventLog)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _debugEventLogRepository.AddAsync(debugEventLog);
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, $"Failure saving DebugEventLog.");
|
||||||
|
throw new ServiceException($"Failure saving DebugEventLog.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Serilog;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class EventLogService : IEventLogService
|
||||||
|
{
|
||||||
|
private readonly IEventLogRepository _eventLogRepository;
|
||||||
|
private readonly IDebugEventLogService _debugEventLogService;
|
||||||
|
private readonly ILoggingMatrixService _loggingMatrixService;
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
|
||||||
|
public EventLogService(IEventLogRepository eventLogRepository,
|
||||||
|
IDebugEventLogService debugEventLogService,
|
||||||
|
ILoggingMatrixService loggingMatrixService,
|
||||||
|
IUnitOfWork unitOfWork)
|
||||||
|
{
|
||||||
|
_eventLogRepository = eventLogRepository;
|
||||||
|
_debugEventLogService = debugEventLogService;
|
||||||
|
_loggingMatrixService = loggingMatrixService;
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleIncomingEventLog(EventLog eventLog)
|
||||||
|
{
|
||||||
|
var loggingMatrixes = await _loggingMatrixService.GetByApplicationLevelAndGroupAsync(eventLog.Application,
|
||||||
|
eventLog.Level,
|
||||||
|
eventLog.Group);
|
||||||
|
if (loggingMatrixes.Any())
|
||||||
|
{
|
||||||
|
await SaveAsync(eventLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _debugEventLogService.DebugEventLog(eventLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<EventLog>> GetAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _eventLogRepository.ListAsync();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = "Failure retrieving EventLogs.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EventLog> SaveAsync(EventLog eventLog)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _eventLogRepository.AddAsync(eventLog);
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure saving EventLog. EventLog: { JsonConvert.SerializeObject(eventLog)}";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteMany(List<EventLog> eventLogs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_eventLogRepository.RemoveRange(eventLogs);
|
||||||
|
_unitOfWork.Complete();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure to delete EventLogs.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public interface IDebugEventLogService
|
||||||
|
{
|
||||||
|
Task DebugEventLog(EventLog eventLog);
|
||||||
|
Task<DebugEventLog> SaveAsync(DebugEventLog debugEventLog);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public interface IEventLogService
|
||||||
|
{
|
||||||
|
Task HandleIncomingEventLog(EventLog eventLog);
|
||||||
|
Task<IEnumerable<EventLog>> GetAsync();
|
||||||
|
Task<EventLog> SaveAsync(EventLog eventLog);
|
||||||
|
void DeleteMany(List<EventLog> eventLogs);
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public interface ILogDistributionService
|
||||||
|
{
|
||||||
|
Task HandleLogDistribution();
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services
|
||||||
|
{
|
||||||
|
public interface ILoggingMatrixService
|
||||||
|
{
|
||||||
|
Task<IEnumerable<LoggingMatrix>> GetAsync();
|
||||||
|
Task<IEnumerable<LoggingMatrix>> GetActiveAsync();
|
||||||
|
Task<LoggingMatrix> GetByIdAsync(int id);
|
||||||
|
Task<IEnumerable<LoggingMatrix>> GetByApplicationLevelAndGroupAsync(string application, string level, string group);
|
||||||
|
Task<IEnumerable<LoggingMatrix>> GetByApplicationAndLevelAsync(string application, string level);
|
||||||
|
Task<LoggingMatrix> SaveAsync(LoggingMatrix loggingMatrix);
|
||||||
|
Task<LoggingMatrix> UpdateAsync(LoggingMatrix loggingMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public interface INotificationsApiService
|
||||||
|
{
|
||||||
|
Task SendNotificationAsync(LoggingMatrix loggingMatrix, List<EventLog> eventLogs);
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public interface IQueueEventLogService
|
||||||
|
{
|
||||||
|
Task QueueEventLog(EventLog request);
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
using Serilog;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class LogDistributionService : ILogDistributionService
|
||||||
|
{
|
||||||
|
private readonly IEventLogService _eventLogService;
|
||||||
|
private readonly ILoggingMatrixService _loggingMatrixService;
|
||||||
|
private readonly INotificationsApiService _notificationsApiService;
|
||||||
|
|
||||||
|
public LogDistributionService(IEventLogService eventLogService,
|
||||||
|
ILoggingMatrixService loggingMatrixService,
|
||||||
|
INotificationsApiService notificationsApiService)
|
||||||
|
{
|
||||||
|
_eventLogService = eventLogService;
|
||||||
|
_loggingMatrixService = loggingMatrixService;
|
||||||
|
_notificationsApiService = notificationsApiService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleLogDistribution()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var eventLogs = await _eventLogService.GetAsync();
|
||||||
|
if(eventLogs == null || !eventLogs.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loggingMatrixs = await _loggingMatrixService.GetActiveAsync();
|
||||||
|
if (loggingMatrixs == null || !loggingMatrixs.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var loggingMatrix in loggingMatrixs)
|
||||||
|
{
|
||||||
|
var matrixEventLogs = eventLogs.Where(eventLog => eventLog.Application == loggingMatrix.Application &&
|
||||||
|
eventLog.Level == loggingMatrix.Level &&
|
||||||
|
eventLog.Group == loggingMatrix.Group).ToList();
|
||||||
|
|
||||||
|
if (!matrixEventLogs.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _notificationsApiService.SendNotificationAsync(loggingMatrix, matrixEventLogs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventLogService.DeleteMany(eventLogs.ToList());
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.Error(exception, "Failure to Handle Log Distribution.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class LoggingMatrixService : ILoggingMatrixService
|
||||||
|
{
|
||||||
|
private readonly ILoggingMatrixRepository _loggingMatrixRepository;
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
|
||||||
|
public LoggingMatrixService(IUnitOfWork unitOfWork,
|
||||||
|
ILoggingMatrixRepository loggingMatrixRepository)
|
||||||
|
{
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_loggingMatrixRepository = loggingMatrixRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> GetAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _loggingMatrixRepository.ListAsync();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = "Failure retrieving Logging Matrixes.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> GetActiveAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _loggingMatrixRepository.ListActiveAsync();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = "Failure retrieving active Logging Matrixes.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> GetByApplicationLevelAndGroupAsync(string application, string level, string group)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _loggingMatrixRepository.RetrieveByApplicationLevelAndGroup(application, level, group);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure retrieving Logging Matrixes with application {application} and level {level}.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> GetByApplicationAndLevelAsync(string application, string level)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _loggingMatrixRepository.RetrieveByApplciationAndLevel(application, level);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure retrieving Logging Matrixes with application {application} and level {level}.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoggingMatrix> GetByIdAsync(int id)
|
||||||
|
{
|
||||||
|
LoggingMatrix loggingMatrix = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
loggingMatrix = await _loggingMatrixRepository.FindByIdAsync(id);
|
||||||
|
return loggingMatrix;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure retrieving Logging Matrix with id {id}.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoggingMatrix> SaveAsync(LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _loggingMatrixRepository.AddAsync(loggingMatrix);
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure saving Logging Matrix. LoggingMatrix: { JsonConvert.SerializeObject(loggingMatrix)}";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoggingMatrix> UpdateAsync(LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var existing = await GetByIdAsync(loggingMatrix.LoggingMatrixId);
|
||||||
|
if (existing == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.Application = loggingMatrix.Application;
|
||||||
|
existing.Level = loggingMatrix.Level;
|
||||||
|
existing.Group = loggingMatrix.Group;
|
||||||
|
existing.Email = loggingMatrix.Email;
|
||||||
|
existing.Disabled = loggingMatrix.Disabled;
|
||||||
|
|
||||||
|
_loggingMatrixRepository.Update(existing);
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure updating Logging Matrix. LoggingMatrix: { JsonConvert.SerializeObject(loggingMatrix)}";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.DataAccesses;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
using LCU.Shared.Common.NotificationApiLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Configurations;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class NotificationsApiService : INotificationsApiService
|
||||||
|
{
|
||||||
|
private readonly ApiConfiguration _apiConfiguration;
|
||||||
|
private readonly INotificationsApiDao _notificationsApiDao;
|
||||||
|
private const string TableRowsTag = "{TableRows}";
|
||||||
|
private const string ApplicationTag = "{Application}";
|
||||||
|
private const string LevelTag = "{Level}";
|
||||||
|
|
||||||
|
public NotificationsApiService(ApiConfiguration apiConfiguration,
|
||||||
|
INotificationsApiDao notificationsApiDao)
|
||||||
|
{
|
||||||
|
_apiConfiguration = apiConfiguration;
|
||||||
|
_notificationsApiDao = notificationsApiDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendNotificationAsync(LoggingMatrix loggingMatrix, List<EventLog> eventLogs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var emailRequest = new EmailRequest
|
||||||
|
{
|
||||||
|
Recipient = new List<string> { loggingMatrix.Email },
|
||||||
|
Subject = $"{loggingMatrix.Application} - {loggingMatrix.Level}",
|
||||||
|
Body = CreateEmailBody(loggingMatrix, eventLogs)
|
||||||
|
};
|
||||||
|
await _notificationsApiDao.SendEmailRequest(emailRequest);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
var message = $"Failure to Send Maidbot Email.";
|
||||||
|
Log.Error(exception, message);
|
||||||
|
throw new ServiceException($"{message} Exception Message: {exception.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateEmailBody(LoggingMatrix loggingMatrix, List<EventLog> eventLogs)
|
||||||
|
{
|
||||||
|
var errorRows = new StringBuilder();
|
||||||
|
foreach(var eventLog in eventLogs)
|
||||||
|
{
|
||||||
|
errorRows.Append(CreateEventLogRow(eventLog));
|
||||||
|
}
|
||||||
|
|
||||||
|
var logEmailTemplateReader = new StreamReader(_apiConfiguration.LogEmailTemplate);
|
||||||
|
string logEmailTemplateOutput = logEmailTemplateReader.ReadToEnd();
|
||||||
|
logEmailTemplateOutput = logEmailTemplateOutput.Replace(TableRowsTag, errorRows.ToString());
|
||||||
|
logEmailTemplateOutput = logEmailTemplateOutput.Replace(ApplicationTag, loggingMatrix.Level);
|
||||||
|
return logEmailTemplateOutput.Replace(LevelTag, loggingMatrix.Application);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateEventLogRow(EventLog eventLog)
|
||||||
|
{
|
||||||
|
var errorRowReader = new StreamReader(_apiConfiguration.LogEmailRowTemplate);
|
||||||
|
string errorRowOutput = errorRowReader.ReadToEnd();
|
||||||
|
|
||||||
|
foreach (var property in eventLog.GetType().GetProperties())
|
||||||
|
{
|
||||||
|
string value = property.GetValue(eventLog) == null ? string.Empty :
|
||||||
|
property.GetValue(eventLog).ToString();
|
||||||
|
errorRowOutput = errorRowOutput.Replace($"{{{property.Name}}}", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorRowOutput;
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MassTransit;
|
||||||
|
using Serilog;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
using LCU.Library.Internal.LcuMassTransitModels;
|
||||||
|
namespace LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
|
||||||
|
public class QueueEventLogService : IQueueEventLogService
|
||||||
|
{
|
||||||
|
private readonly ISendEndpoint _sendEndpoint;
|
||||||
|
|
||||||
|
public QueueEventLogService(IBusControl busControl,
|
||||||
|
ReceiveEndpointConfiguration receiveEndpointConfiguration)
|
||||||
|
{
|
||||||
|
_sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfiguration.ReceiveEndpointUri).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task QueueEventLog(EventLog request)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
||||||
|
await _sendEndpoint.Send(request, cancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
|
||||||
|
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
|
||||||
|
.Fatal(exception, "Failed to Queue EventLog Request.");
|
||||||
|
throw new ServiceException("Failed to Queue EventLog Request.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
<tr id="errorRow" style="height: 22px;">
|
||||||
|
<td style="max-width: 50px;">{LogTimeStamp}</td>
|
||||||
|
<td style="max-width: 300px;">{Message}</td>
|
||||||
|
</tr>
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#errors {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errors td, #errors th {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errors tr:nth-child(even) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errors th {
|
||||||
|
padding-top: 12px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#emailHeader {
|
||||||
|
color: #0054a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errorTableHeader {
|
||||||
|
background-color: #0054a2;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>MaidBot: {Application} Event Logs</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><span id="emailHeader">MaidBot: {Application} {Level} Event Logs</span></h1>
|
||||||
|
<table id="errors">
|
||||||
|
<thead id="errorTableHeader">
|
||||||
|
<tr style="height: 17px;">
|
||||||
|
<td style="max-width: 50px;font-weight: bolder;">Timestamp</td>
|
||||||
|
<td style="max-width: 300px; font-weight: bolder;">Log Details</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="errorRows">
|
||||||
|
{TableRows}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"Primary": {
|
||||||
|
"AppName": "MaidBot Api",
|
||||||
|
"SeqUrl": "http://localhost:5080",
|
||||||
|
"SeqApiKey": "VALUE-IN-KEYVAULT",
|
||||||
|
"NotificationsApiEmail": "https://localhost:50353/api/Email",
|
||||||
|
"FeatureFlags": {
|
||||||
|
"LoggingEventConsumer": true,
|
||||||
|
"RunScheduler": true
|
||||||
|
},
|
||||||
|
"BatchSchedulerCron": "*/5 * * * *",
|
||||||
|
"CorsAllowedOrigins": [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"http://lcu-internal.com",
|
||||||
|
"https://lcu-internal.com",
|
||||||
|
"https://qa-api.lcu-internal.com",
|
||||||
|
"https://uat-api.lcu-internal.com",
|
||||||
|
"https://api.lcu-internal.com"
|
||||||
|
],
|
||||||
|
"LogEmailTemplate": "./Templates/LogEmailTemplate.html",
|
||||||
|
"LogEmailRowTemplate": "./Templates/LogEmailRowTemplate.html"
|
||||||
|
},
|
||||||
|
"ConnectionConfiguration": {
|
||||||
|
"HostUrl": "localhost",
|
||||||
|
"UserName": "guest",
|
||||||
|
"Password": "guest"
|
||||||
|
},
|
||||||
|
"ReceiveEndpoint": {
|
||||||
|
"ReceiveEndpoint": "LCU.MaidBot",
|
||||||
|
"ReceiveEndpointType": "exchange",
|
||||||
|
"PrefetchLimit": 1
|
||||||
|
},
|
||||||
|
"Connections": {
|
||||||
|
"SQL": {
|
||||||
|
"MaidBotDB": "data source=localhost;initial catalog=MaidBot;Integrated Security=SSPI;MultipleActiveResultSets=True;App=EntityFramework"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<Version>1.0.2</Version>
|
||||||
|
<Description>
|
||||||
|
1.0.0 - Initial Creation
|
||||||
|
1.0.1 - Add BusinessOperations Group Enum
|
||||||
|
1.0.2 - Add IndirectLending Group Enum
|
||||||
|
</Description>
|
||||||
|
<PackageReleaseNotes>
|
||||||
|
1.0.0 - Initial Creation
|
||||||
|
1.0.1 - Add BusinessOperations Group Enum
|
||||||
|
1.0.2 - Add IndirectLending Group Enum
|
||||||
|
</PackageReleaseNotes>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.10" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.10" />
|
||||||
|
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace LCU.Api.Internal.MaidBotLib.Models
|
||||||
|
{
|
||||||
|
public class DebugEventLog
|
||||||
|
{
|
||||||
|
public const int DebugMaxLength = 3000;
|
||||||
|
|
||||||
|
public DebugEventLog()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebugEventLog(EventLog eventLog)
|
||||||
|
{
|
||||||
|
RawLog = eventLog.DebugData.Length > DebugMaxLength ? eventLog.DebugData.Substring(0, DebugMaxLength) : eventLog.DebugData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DebugEventLogId { get; set; }
|
||||||
|
public string RawLog { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Models
|
||||||
|
{
|
||||||
|
public class EventLog
|
||||||
|
{
|
||||||
|
public int EventLogId { get; set; }
|
||||||
|
public string Application { get; set; }
|
||||||
|
public string Level { get; set; }
|
||||||
|
public string Group { get; set; }
|
||||||
|
public DateTime LogTimeStamp { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public string Environment { get; set; }
|
||||||
|
public string DebugData { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Models
|
||||||
|
{
|
||||||
|
public enum GroupEnum
|
||||||
|
{
|
||||||
|
Testing,
|
||||||
|
ITDevelopment,
|
||||||
|
BusinessOperations,
|
||||||
|
IndirectLending
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Models
|
||||||
|
{
|
||||||
|
public class LoggingMatrix
|
||||||
|
{
|
||||||
|
public int LoggingMatrixId { get; set; }
|
||||||
|
[StringLength(200, MinimumLength = 1, ErrorMessage = "Application field must have a length between 1 and 200 characters")]
|
||||||
|
public string Application { get; set; }
|
||||||
|
[StringLength(50, MinimumLength = 1, ErrorMessage = "Level field must have a length between 1 and 50 characters")]
|
||||||
|
public string Level { get; set; }
|
||||||
|
[StringLength(100, MinimumLength = 1, ErrorMessage = "Groups field must have a length between 1 and 100 characters")]
|
||||||
|
public string Group { get; set; }
|
||||||
|
[StringLength(100, MinimumLength = 1, ErrorMessage = "Emails field must have a length between 1 and 100 characters")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace LCU.Api.Internal.MaidBotLib.Models
|
||||||
|
{
|
||||||
|
public enum PropertyEnum
|
||||||
|
{
|
||||||
|
Group
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Persistence
|
||||||
|
{
|
||||||
|
public class AppDbContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<LoggingMatrix> LoggingMatrixs { get; set; }
|
||||||
|
public DbSet<EventLog> EventLogs { get; set; }
|
||||||
|
public DbSet<DebugEventLog> DebugEventLogs { get; set; }
|
||||||
|
|
||||||
|
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
builder.Entity<LoggingMatrix>().ToTable("LoggingMatrix");
|
||||||
|
builder.Entity<EventLog>().ToTable("EventLog");
|
||||||
|
builder.Entity<DebugEventLog>().ToTable("DebugEventLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public abstract class BaseRepository
|
||||||
|
{
|
||||||
|
protected readonly AppDbContext _context;
|
||||||
|
|
||||||
|
public BaseRepository(AppDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public class DebugEventLogRepository : BaseRepository, IDebugEventLogRepository
|
||||||
|
{
|
||||||
|
public DebugEventLogRepository(AppDbContext context) : base(context) { }
|
||||||
|
|
||||||
|
public async Task<DebugEventLog> AddAsync(DebugEventLog debugEventLog)
|
||||||
|
{
|
||||||
|
var result = await _context.DebugEventLogs.AddAsync(debugEventLog);
|
||||||
|
return result.Entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public class EventLogRepository : BaseRepository, IEventLogRepository
|
||||||
|
{
|
||||||
|
public EventLogRepository(AppDbContext context) : base(context) { }
|
||||||
|
|
||||||
|
public async Task<IEnumerable<EventLog>> ListAsync()
|
||||||
|
{
|
||||||
|
return await _context.EventLogs.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EventLog> AddAsync(EventLog eventLog)
|
||||||
|
{
|
||||||
|
var result = await _context.EventLogs.AddAsync(eventLog);
|
||||||
|
return result.Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRange(List<EventLog> eventLog)
|
||||||
|
{
|
||||||
|
_context.EventLogs.RemoveRange(eventLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public interface IDebugEventLogRepository
|
||||||
|
{
|
||||||
|
Task<DebugEventLog> AddAsync(DebugEventLog debugEventLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public interface IEventLogRepository
|
||||||
|
{
|
||||||
|
Task<IEnumerable<EventLog>> ListAsync();
|
||||||
|
Task<EventLog> AddAsync(EventLog eventLog);
|
||||||
|
void RemoveRange(List<EventLog> eventLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public interface ILoggingMatrixRepository
|
||||||
|
{
|
||||||
|
Task<IEnumerable<LoggingMatrix>> ListAsync();
|
||||||
|
Task<IEnumerable<LoggingMatrix>> ListActiveAsync();
|
||||||
|
Task<LoggingMatrix> FindByIdAsync(int id);
|
||||||
|
Task<IEnumerable<LoggingMatrix>> RetrieveByApplicationLevelAndGroup(string application, string level, string group);
|
||||||
|
Task<IEnumerable<LoggingMatrix>> RetrieveByApplciationAndLevel(string application, string level);
|
||||||
|
Task<LoggingMatrix> AddAsync(LoggingMatrix loggingMatrix);
|
||||||
|
void Update(LoggingMatrix loggingMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public interface IUnitOfWork
|
||||||
|
{
|
||||||
|
Task CompleteAsync();
|
||||||
|
void Complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public class LoggingMatrixRepository : BaseRepository, ILoggingMatrixRepository
|
||||||
|
{
|
||||||
|
public LoggingMatrixRepository(AppDbContext context) : base(context) { }
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> ListAsync()
|
||||||
|
{
|
||||||
|
return await _context.LoggingMatrixs.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> ListActiveAsync()
|
||||||
|
{
|
||||||
|
return await _context.LoggingMatrixs.Where(loggingMatrix => !loggingMatrix.Disabled).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoggingMatrix> FindByIdAsync(int id)
|
||||||
|
{
|
||||||
|
return await _context.LoggingMatrixs.Where(loggingMatrix => loggingMatrix.LoggingMatrixId == id).FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> RetrieveByApplicationLevelAndGroup(string application, string level, string group)
|
||||||
|
{
|
||||||
|
return await _context.LoggingMatrixs
|
||||||
|
.Where(matrix => matrix.Application == application &&
|
||||||
|
matrix.Level == level &&
|
||||||
|
matrix.Group == group &&
|
||||||
|
!matrix.Disabled)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<LoggingMatrix>> RetrieveByApplciationAndLevel(string application, string level)
|
||||||
|
{
|
||||||
|
return await _context.LoggingMatrixs
|
||||||
|
.Where(matrix => matrix.Application == application &&
|
||||||
|
matrix.Level == level &&
|
||||||
|
!matrix.Disabled)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoggingMatrix> AddAsync(LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
var result = await _context.LoggingMatrixs.AddAsync(loggingMatrix);
|
||||||
|
return result.Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(LoggingMatrix loggingMatrix)
|
||||||
|
{
|
||||||
|
_context.LoggingMatrixs.Update(loggingMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotLib.Repositories
|
||||||
|
{
|
||||||
|
public class UnitOfWork : IUnitOfWork
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _context;
|
||||||
|
|
||||||
|
public UnitOfWork(AppDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CompleteAsync()
|
||||||
|
{
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Complete()
|
||||||
|
{
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
<Description>LCU.Api.Internal.MaidBotSeqApp</Description>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.9" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
|
<PackageReference Include="Seq.Apps" Version="5.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LCU.Api.Internal.MaidBotLib\LCU.Api.Internal.MaidBotLib.csproj" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="BuildOnlySettings;ResolveReferences">
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Filter out unnecessary files -->
|
||||||
|
<_ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Print batches for debug purposes -->
|
||||||
|
<Message Text="Batch for .nupkg: ReferenceCopyLocalPaths = @(_ReferenceCopyLocalPaths), ReferenceCopyLocalPaths.DestinationSubDirectory = %(_ReferenceCopyLocalPaths.DestinationSubDirectory) Filename = %(_ReferenceCopyLocalPaths.Filename) Extension = %(_ReferenceCopyLocalPaths.Extension)" Importance="High" Condition="'@(_ReferenceCopyLocalPaths)' != ''" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Add file to package with consideration of sub folder. If empty, the root folder is chosen. -->
|
||||||
|
<BuildOutputInPackage Include="@(_ReferenceCopyLocalPaths)" TargetPath="%(_ReferenceCopyLocalPaths.DestinationSubDirectory)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Seq.Apps;
|
||||||
|
using Seq.Apps.LogEvents;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotSeqApp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Queues LogEvent.
|
||||||
|
/// </summary>
|
||||||
|
[SeqApp("QueueLogs", Description = "This will queue logs based on a signal event")]
|
||||||
|
public class SeqToRabbit : SeqApp, ISubscribeTo<LogEventData>
|
||||||
|
{
|
||||||
|
private static readonly HttpClient _client = new HttpClient();
|
||||||
|
|
||||||
|
[SeqAppSetting(DisplayName = "Url", HelpText = "Url of MaidBot")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
[SeqAppSetting(DisplayName = "DebugMode", HelpText = "Setting this will set DebugData field to the events serialized object and save to our DebugEventLog database table.")]
|
||||||
|
public bool DebugMode { get; set; }
|
||||||
|
|
||||||
|
protected override void OnAttached()
|
||||||
|
{
|
||||||
|
base.OnAttached();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by Seq whenever an event is sent to the app
|
||||||
|
public void On(Event<LogEventData> evt)
|
||||||
|
{
|
||||||
|
EventLog logRequest = CreateLogRequest(evt);
|
||||||
|
|
||||||
|
if(logRequest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueLogEvent(logRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MissingRequiredFields(Event<LogEventData> evt)
|
||||||
|
{
|
||||||
|
return evt == null ||
|
||||||
|
evt.Data == null ||
|
||||||
|
evt.Data.RenderedMessage == null ||
|
||||||
|
evt.Data.Properties == null ||
|
||||||
|
!evt.Data.Properties.ContainsKey("Application") ||
|
||||||
|
!evt.Data.Properties.ContainsKey("Group");
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventLog CreateLogRequest(Event<LogEventData> evt)
|
||||||
|
{
|
||||||
|
var eventLog = new EventLog();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (MissingRequiredFields(evt))
|
||||||
|
{
|
||||||
|
Log.Debug("Seq LogEventData missing required fields to be logged by MaidBot.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventLog.Application = evt.Data.Properties["Application"].ToString();
|
||||||
|
eventLog.Level = Enum.GetName(typeof(LogEventLevel), evt.Data.Level);
|
||||||
|
eventLog.LogTimeStamp = evt.TimestampUtc;
|
||||||
|
eventLog.Message = evt.Data.RenderedMessage;
|
||||||
|
eventLog.Group = evt.Data.Properties["Group"].ToString();
|
||||||
|
eventLog.Environment = evt.Data.Properties.ContainsKey("Environment") ? evt.Data.Properties["Environment"].ToString() : "";
|
||||||
|
eventLog.DebugData = DebugMode ? JsonConvert.SerializeObject(evt) : "";
|
||||||
|
|
||||||
|
return eventLog;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Log.Debug(ex, "[Error] MaidBot: Error Creating Event Log.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueLogEvent(EventLog eventLog)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var encodedContent = JsonConvert.SerializeObject(eventLog);
|
||||||
|
var content = new StringContent(encodedContent, Encoding.UTF8, "application/json");
|
||||||
|
HttpResponseMessage response = _client.PostAsync(Url, content).Result;
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Log.Debug("[Error] Failure to send Event Log to MaidBot.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Log.Debug(ex, "[Error] MaidBot: Failure to send Event Log to MaidBot.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE [dbo].[DebugEventLog]
|
||||||
|
(
|
||||||
|
[DebugEventLogId] INT NOT NULL PRIMARY KEY IDENTITY,
|
||||||
|
[RawLog] VARCHAR(3000) NULL
|
||||||
|
)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE [dbo].[EventLog]
|
||||||
|
(
|
||||||
|
[EventLogId] INT NOT NULL PRIMARY KEY IDENTITY,
|
||||||
|
[Application] VARCHAR(500) NOT NULL,
|
||||||
|
[Level] VARCHAR(100) NOT NULL,
|
||||||
|
[Group] VARCHAR(200) NOT NULL,
|
||||||
|
[LogTimeStamp] DATETIME NOT NULL,
|
||||||
|
[Message] VARCHAR(MAX) NOT NULL,
|
||||||
|
[Environment] VARCHAR(100) NOT NULL,
|
||||||
|
[DebugData] VARCHAR(MAX) NULL
|
||||||
|
)
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Operations Version="1.0" xmlns="http://schemas.microsoft.com/sqlserver/dac/Serialization/2012/02">
|
||||||
|
<Operation Name="Rename Refactor" Key="f8dee825-d461-43d7-a087-e525edf88ec9" ChangeDateTime="10/19/2020 20:57:13">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[LoggingMatrix].[Id]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[LoggingMatrix]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="LoggingMatrixId" />
|
||||||
|
</Operation>
|
||||||
|
<Operation Name="Rename Refactor" Key="640cc9fc-bf7e-4fc8-9e7a-d2be37aed364" ChangeDateTime="10/19/2020 20:58:44">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[LoggingMatrix].[Group]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[LoggingMatrix]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="Groups" />
|
||||||
|
</Operation>
|
||||||
|
<Operation Name="Rename Refactor" Key="76e86eb1-05aa-4265-82bf-d15789e45591" ChangeDateTime="10/20/2020 17:47:01">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[LoggingMatrix].[Groups]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[LoggingMatrix]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="Group" />
|
||||||
|
</Operation>
|
||||||
|
<Operation Name="Rename Refactor" Key="af161f35-aff3-44c9-a19a-2f4f4959965d" ChangeDateTime="10/20/2020 17:47:03">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[LoggingMatrix].[Emails]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[LoggingMatrix]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="Email" />
|
||||||
|
</Operation>
|
||||||
|
<Operation Name="Rename Refactor" Key="6122a340-340c-4e01-a932-b1cafcccd65c" ChangeDateTime="10/23/2020 13:36:33">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[DebugEventLogs].[Id]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[DebugEventLogs]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="DebugEventLogId" />
|
||||||
|
</Operation>
|
||||||
|
<Operation Name="Rename Refactor" Key="8d26ed1b-e4e8-4636-ab40-ac133403cdb4" ChangeDateTime="07/11/2022 23:59:06">
|
||||||
|
<Property Name="ElementName" Value="[dbo].[EventLog].[Id]" />
|
||||||
|
<Property Name="ElementType" Value="SqlSimpleColumn" />
|
||||||
|
<Property Name="ParentElementName" Value="[dbo].[EventLog]" />
|
||||||
|
<Property Name="ParentElementType" Value="SqlTable" />
|
||||||
|
<Property Name="NewName" Value="EventLogId" />
|
||||||
|
</Operation>
|
||||||
|
</Operations>
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<Name>LCU.Api.Internal.MaidBotSql</Name>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectVersion>4.1</ProjectVersion>
|
||||||
|
<ProjectGuid>{ecce6677-a2f2-4694-964f-f91ebe7aac00}</ProjectGuid>
|
||||||
|
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider</DSP>
|
||||||
|
<OutputType>Database</OutputType>
|
||||||
|
<RootPath>
|
||||||
|
</RootPath>
|
||||||
|
<RootNamespace>LCU.Api.Internal.MaidBotSql</RootNamespace>
|
||||||
|
<AssemblyName>LCU.Api.Internal.MaidBotSql</AssemblyName>
|
||||||
|
<ModelCollation>1033, CI</ModelCollation>
|
||||||
|
<DefaultFileStructure>BySchemaAndSchemaType</DefaultFileStructure>
|
||||||
|
<DeployToDatabase>True</DeployToDatabase>
|
||||||
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
|
<TargetLanguage>CS</TargetLanguage>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<SqlServerVerification>False</SqlServerVerification>
|
||||||
|
<IncludeCompositeObjects>True</IncludeCompositeObjects>
|
||||||
|
<TargetDatabaseSet>True</TargetDatabaseSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||||
|
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DefineDebug>false</DefineDebug>
|
||||||
|
<DefineTrace>true</DefineTrace>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||||
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<DefineDebug>true</DefineDebug>
|
||||||
|
<DefineTrace>true</DefineTrace>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||||
|
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
|
||||||
|
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
|
||||||
|
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||||
|
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Properties" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Build Include="LoggingMatrix.sql" />
|
||||||
|
<Build Include="DebugEventLog.sql" />
|
||||||
|
<Build Include="EventLog.sql" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<RefactorLog Include="LCU.Api.Internal.MaidBotSql.refactorlog" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE [dbo].[LoggingMatrix]
|
||||||
|
(
|
||||||
|
[LoggingMatrixId] INT NOT NULL PRIMARY KEY IDENTITY,
|
||||||
|
[Application] VARCHAR(200) NOT NULL,
|
||||||
|
[Level] VARCHAR(50) NOT NULL,
|
||||||
|
[Group] VARCHAR(100) NOT NULL,
|
||||||
|
[Email] VARCHAR(100) NOT NULL,
|
||||||
|
[Disabled] BIT NULL
|
||||||
|
)
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ControllerTests;
|
||||||
|
|
||||||
|
public class LoggingMatrixControllerTest
|
||||||
|
{
|
||||||
|
private readonly LoggingMatrixController _loggingMatrixController;
|
||||||
|
private readonly Mock<ILoggingMatrixService> _mockLoggingMatrixService;
|
||||||
|
|
||||||
|
public LoggingMatrixControllerTest()
|
||||||
|
{
|
||||||
|
_mockLoggingMatrixService = new Mock<ILoggingMatrixService>();
|
||||||
|
_loggingMatrixController = new LoggingMatrixController(_mockLoggingMatrixService.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void GetAllLoggingMatrix_Success_200()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixService.Setup(service => service.GetAsync()).ReturnsAsync(new List<LoggingMatrix>
|
||||||
|
{
|
||||||
|
new LoggingMatrix(),
|
||||||
|
new LoggingMatrix()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Get();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as OkObjectResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.NotNull(okResult.Value);
|
||||||
|
|
||||||
|
var extractedValue = okResult.Value as IEnumerable<LoggingMatrix>;
|
||||||
|
Assert.NotNull(extractedValue);
|
||||||
|
Assert.Equal(2, extractedValue.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void GetAllLoggingMatrix_BsaCorrectionServiceThrowsError_500()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixService.Setup(service => service.GetAsync()).ThrowsAsync(new Exception());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Get();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as StatusCodeResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.Equal(StatusCodes.Status500InternalServerError, okResult.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void PostLoggingMatrix_LoggingMatrixReturnsNull_BadRequest400()
|
||||||
|
{
|
||||||
|
var loggingMatrix = new LoggingMatrix() { };
|
||||||
|
_mockLoggingMatrixService.Setup(service => service.SaveAsync(loggingMatrix)).ReturnsAsync(() => null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Post(loggingMatrix);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as ObjectResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.Equal(StatusCodes.Status400BadRequest, okResult.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void PostLoggingMatrix_throwsException_500()
|
||||||
|
{
|
||||||
|
var loggingMatrix = new LoggingMatrix() { };
|
||||||
|
_mockLoggingMatrixService.Setup(service => service.SaveAsync(loggingMatrix)).Throws(new Exception("Exception from unit test"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Post(loggingMatrix);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as StatusCodeResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.Equal(StatusCodes.Status500InternalServerError, okResult.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void PutLoggingMatrix_BadRequestIdEqualZero_400()
|
||||||
|
{
|
||||||
|
var loggingMatrix = new LoggingMatrix
|
||||||
|
{
|
||||||
|
LoggingMatrixId = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Put(loggingMatrix);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var returnedResult = result as BadRequestObjectResult;
|
||||||
|
Assert.NotNull(returnedResult);
|
||||||
|
Assert.Equal(StatusCodes.Status400BadRequest, returnedResult.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void PutLoggingMatrix_ThrowsException_500()
|
||||||
|
{
|
||||||
|
var loggingMatrix = new LoggingMatrix
|
||||||
|
{
|
||||||
|
LoggingMatrixId = 1
|
||||||
|
};
|
||||||
|
_mockLoggingMatrixService.Setup(service => service.UpdateAsync(loggingMatrix)).Throws(new Exception("Exception from update unit test"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixController.Put(loggingMatrix);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as StatusCodeResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.Equal(StatusCodes.Status500InternalServerError, okResult.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.API.Internal.MaidBotApi.Controllers;
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ControllerTests;
|
||||||
|
|
||||||
|
public class QueueEventLogControllerTest
|
||||||
|
{
|
||||||
|
private readonly QueueEventLogController _queueEventLogController;
|
||||||
|
private readonly Mock<IQueueEventLogService> _mockQueueEventLogService;
|
||||||
|
|
||||||
|
public QueueEventLogControllerTest()
|
||||||
|
{
|
||||||
|
_mockQueueEventLogService = new Mock<IQueueEventLogService>();
|
||||||
|
_queueEventLogController = new QueueEventLogController(_mockQueueEventLogService.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PostLoggingMatrix_throwsException_500()
|
||||||
|
{
|
||||||
|
var eventLog = new EventLog() { };
|
||||||
|
_mockQueueEventLogService.Setup(service => service.QueueEventLog(eventLog)).Throws(new Exception("Exception from unit test"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _queueEventLogController.Post(eventLog);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var okResult = result as StatusCodeResult;
|
||||||
|
Assert.NotNull(okResult);
|
||||||
|
Assert.Equal(StatusCodes.Status500InternalServerError, okResult.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.6" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
|
||||||
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.0" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LCU.API.Internal.MaidBotApi\LCU.Api.Internal.MaidBotApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="RepositoryTests\LoggingMatrixTestData.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ModelTest
|
||||||
|
{
|
||||||
|
public class DebugEventLogTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CreateDebugEventLog_RawLog_LengthToLong_TrimToMax()
|
||||||
|
{
|
||||||
|
// Arrange / Act
|
||||||
|
var testEventLog = new EventLog();
|
||||||
|
testEventLog.DebugData = "TESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETETESTTESTETSETETSETSETSETSETSETSETSETETESTSETSETSETSETSETESTESTESTSETSETSETSETSTESTETEETE";
|
||||||
|
var debugEventLog = new DebugEventLog(testEventLog);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(debugEventLog);
|
||||||
|
Assert.Equal(DebugEventLog.DebugMaxLength, debugEventLog.RawLog.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Persistence;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.RepositoryTests
|
||||||
|
{
|
||||||
|
public class DbContextTestSet
|
||||||
|
{
|
||||||
|
public IReadOnlyCollection<LoggingMatrix> LoggingMatrixSet { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class DbContextFromJsonTest
|
||||||
|
{
|
||||||
|
public DbContextTestSet GetTestAccounts(string filePath)
|
||||||
|
{
|
||||||
|
var testSet = new DbContextTestSet();
|
||||||
|
|
||||||
|
// Get the absolute path to the JSON file
|
||||||
|
var path = Path.IsPathRooted(filePath)
|
||||||
|
? filePath
|
||||||
|
: Path.GetRelativePath(Directory.GetCurrentDirectory(), filePath);
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Could not find file at path: {path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileData = File.ReadAllText(filePath);
|
||||||
|
var allData = JObject.Parse(fileData);
|
||||||
|
|
||||||
|
var runInfo = allData["LoggingMatrixs"];
|
||||||
|
testSet.LoggingMatrixSet = runInfo?.ToObject<List<LoggingMatrix>>();
|
||||||
|
|
||||||
|
return testSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppDbContext GetBlankContext()
|
||||||
|
{
|
||||||
|
var options = new DbContextOptionsBuilder<AppDbContext>()
|
||||||
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||||
|
.Options;
|
||||||
|
return new AppDbContext(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppDbContext GetContextWithData(string jsonFileName)
|
||||||
|
{
|
||||||
|
var options = new DbContextOptionsBuilder<AppDbContext>()
|
||||||
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||||
|
.Options;
|
||||||
|
var context = new AppDbContext(options);
|
||||||
|
|
||||||
|
var testData = GetTestAccounts(jsonFileName);
|
||||||
|
AddTo(context.LoggingMatrixs, testData.LoggingMatrixSet);
|
||||||
|
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddTo<T>(DbSet<T> collection, IEnumerable<T> range) where T : class
|
||||||
|
{
|
||||||
|
if (range != null) collection.AddRange(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.RepositoryTests
|
||||||
|
{
|
||||||
|
public class LoggingMatrixRepositoryTest : DbContextFromJsonTest
|
||||||
|
{
|
||||||
|
private readonly LoggingMatrixRepository _loggingMatrixRepository;
|
||||||
|
private const string JsonTestDataFilePath = "RepositoryTests\\LoggingMatrixTestData.json";
|
||||||
|
|
||||||
|
public LoggingMatrixRepositoryTest()
|
||||||
|
{
|
||||||
|
var dbContext = GetContextWithData(JsonTestDataFilePath);
|
||||||
|
_loggingMatrixRepository = new LoggingMatrixRepository(dbContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: These UnitTest have been commented out since there is version mismatch and at this time
|
||||||
|
// we are not going to undergo the work that is required to upgrade. The work to upgrade
|
||||||
|
// the .net version will need to be done in a separate Story:
|
||||||
|
// 89988 Maidbot API > Library Modernization
|
||||||
|
// https://landmarkcu.visualstudio.com/LMCU/_boards/board/t/Development/Stories?workitem=89988.
|
||||||
|
// This decision was made during this PR:
|
||||||
|
// https://landmarkcu.visualstudio.com/Platform/_git/LCU.API.Internal.MaidBotApi/pullrequest/17634
|
||||||
|
//[Fact]
|
||||||
|
//public void ListAsync_Test()
|
||||||
|
//{
|
||||||
|
// var loggingMatrixes = _loggingMatrixRepository.ListAsync().Result;
|
||||||
|
// Assert.NotNull(loggingMatrixes);
|
||||||
|
// Assert.Equal(6, loggingMatrixes.Count());
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Fact]
|
||||||
|
//public async void FindById_Test()
|
||||||
|
//{
|
||||||
|
// var loggingMatrix = await _loggingMatrixRepository.FindByIdAsync(1);
|
||||||
|
// Assert.NotNull(loggingMatrix);
|
||||||
|
// Assert.Equal(1, loggingMatrix.LoggingMatrixId);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Fact]
|
||||||
|
//public void RetrieveByApplicationLevelAndGroup_Test()
|
||||||
|
//{
|
||||||
|
// var application = "Test App 1";
|
||||||
|
// var group = "Test Group 1";
|
||||||
|
// var level = "Test Level 1";
|
||||||
|
// var loggingMatrixes = _loggingMatrixRepository.RetrieveByApplicationLevelAndGroup(application, level, group ).Result;
|
||||||
|
// Assert.NotNull(loggingMatrixes);
|
||||||
|
// Assert.Equal(2, loggingMatrixes.Count());
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[Fact]
|
||||||
|
//public void RetrieveByApplciationAndLevel_Test()
|
||||||
|
//{
|
||||||
|
// var application = "Test App 1";
|
||||||
|
// var level = "Test Level 1";
|
||||||
|
// var loggingMatrixes = _loggingMatrixRepository.RetrieveByApplciationAndLevel(application, level).Result;
|
||||||
|
// Assert.NotNull(loggingMatrixes);
|
||||||
|
// Assert.Equal(3, loggingMatrixes.Count());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"LoggingMatrixs": [
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 1,
|
||||||
|
"Application": "Test App 1",
|
||||||
|
"Level": "Test Level 1",
|
||||||
|
"Group": "Test Group 1",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 2,
|
||||||
|
"Application": "Test App 2",
|
||||||
|
"Level": "Test Level 2",
|
||||||
|
"Group": "Test Group 2",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 3,
|
||||||
|
"Application": "Test App 3",
|
||||||
|
"Level": "Test Level 3",
|
||||||
|
"Group": "Test Group 3",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 4,
|
||||||
|
"Application": "Test App 1",
|
||||||
|
"Level": "Test Level 1",
|
||||||
|
"Group": "Test Group 1",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 5,
|
||||||
|
"Application": "Test App 1",
|
||||||
|
"Level": "Test Level 1",
|
||||||
|
"Group": "Test Group 1",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LoggingmatrixId": 6,
|
||||||
|
"Application": "Test App 1",
|
||||||
|
"Level": "Test Level 1",
|
||||||
|
"Group": "Test Group 6",
|
||||||
|
"Email": "[email protected]",
|
||||||
|
"Disabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Exceptions;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ServiceTests;
|
||||||
|
|
||||||
|
public class DebugEventLogServiceTest
|
||||||
|
{
|
||||||
|
private readonly DebugEventLogService _debugEventLogService;
|
||||||
|
private readonly Mock<IDebugEventLogRepository> _mockDebugEventLogRepository;
|
||||||
|
|
||||||
|
public DebugEventLogServiceTest()
|
||||||
|
{
|
||||||
|
var mockUnitOfWork = new Mock<IUnitOfWork>();
|
||||||
|
_mockDebugEventLogRepository = new Mock<IDebugEventLogRepository>();
|
||||||
|
_debugEventLogService = new DebugEventLogService(mockUnitOfWork.Object, _mockDebugEventLogRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SaveAsync_Success()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockDebugEventLogRepository.Setup(repo => repo.AddAsync(It.IsAny<DebugEventLog>())).ReturnsAsync(new DebugEventLog());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _debugEventLogService.SaveAsync(new DebugEventLog());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SaveAsync_Exception_Throws_ServerError()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockDebugEventLogRepository.Setup(repo => repo.AddAsync(It.IsAny<DebugEventLog>())).ThrowsAsync(new Exception());
|
||||||
|
|
||||||
|
// Act / Assert
|
||||||
|
await Assert.ThrowsAsync<ServiceException>(async () =>
|
||||||
|
await _debugEventLogService.SaveAsync(new DebugEventLog()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DebugEventLog_Verify_AddAsyncCalled_Once()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testEventLog = new EventLog()
|
||||||
|
{
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
};
|
||||||
|
var testDebugEventLog = new DebugEventLog()
|
||||||
|
{
|
||||||
|
RawLog = "Test Debug Data"
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockDebugEventLogRepository.Setup(repo => repo.AddAsync(testDebugEventLog)).ReturnsAsync(testDebugEventLog);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await _debugEventLogService.DebugEventLog(testEventLog);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
_mockDebugEventLogRepository.Verify(x => x.AddAsync(It.IsAny<DebugEventLog>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DebugEventLog_Verify_AddAsyncCalled_Never()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testEventLog = new EventLog() { };
|
||||||
|
_mockDebugEventLogRepository.Setup(repo => repo.AddAsync(It.IsAny<DebugEventLog>())).ReturnsAsync(new DebugEventLog());
|
||||||
|
var testDebugEventLog = new DebugEventLog();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await _debugEventLogService.DebugEventLog(testEventLog);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
_mockDebugEventLogRepository.Verify(x => x.AddAsync(testDebugEventLog), Times.Never);
|
||||||
|
}
|
||||||
|
}
|
||||||
+170
@@ -0,0 +1,170 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ServiceTests;
|
||||||
|
|
||||||
|
public class EventLogServiceTest
|
||||||
|
{
|
||||||
|
private EventLogService _eventLogService;
|
||||||
|
private readonly Mock<IEventLogRepository> _mockEventLogRepository;
|
||||||
|
private readonly Mock<IDebugEventLogService> _mockDebugEventLogService;
|
||||||
|
private readonly Mock<ILoggingMatrixService> _mockLoggingMatrixService;
|
||||||
|
private readonly Mock<IUnitOfWork> _mockUnitOfWork;
|
||||||
|
|
||||||
|
public EventLogServiceTest()
|
||||||
|
{
|
||||||
|
_mockEventLogRepository = new Mock<IEventLogRepository>();
|
||||||
|
_mockDebugEventLogService = new Mock<IDebugEventLogService>();
|
||||||
|
_mockLoggingMatrixService = new Mock<ILoggingMatrixService>();
|
||||||
|
_mockUnitOfWork = new Mock<IUnitOfWork>();
|
||||||
|
|
||||||
|
_eventLogService = new EventLogService(_mockEventLogRepository.Object,
|
||||||
|
_mockDebugEventLogService.Object,
|
||||||
|
_mockLoggingMatrixService.Object,
|
||||||
|
_mockUnitOfWork.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleEventLog_AllMethods_Called_Once()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testEventLog = new EventLog
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
};
|
||||||
|
|
||||||
|
var testLoggingMatrix = new List<LoggingMatrix>
|
||||||
|
{
|
||||||
|
new LoggingMatrix
|
||||||
|
{
|
||||||
|
LoggingMatrixId = 1,
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
Email = "[email protected]",
|
||||||
|
Disabled = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_mockLoggingMatrixService.Setup(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(testLoggingMatrix);
|
||||||
|
|
||||||
|
var eventLogResult = new EventLog
|
||||||
|
{
|
||||||
|
EventLogId = 1,
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
};
|
||||||
|
_mockEventLogRepository.Setup(x => x.AddAsync(It.IsAny<EventLog>())).ReturnsAsync(eventLogResult);
|
||||||
|
_mockDebugEventLogService.Setup(x => x.DebugEventLog(It.IsAny<EventLog>()));
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await _eventLogService.HandleIncomingEventLog(testEventLog);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
|
_mockEventLogRepository.Verify(x => x.AddAsync(It.IsAny<EventLog>()), Times.Once);
|
||||||
|
_mockDebugEventLogService.Verify(x => x.DebugEventLog(It.IsAny<EventLog>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleEventLog_NoMatrixFound_EventLogNotSaved()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testEventLog = new EventLog()
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = null
|
||||||
|
};
|
||||||
|
|
||||||
|
var testLoggingMatrix = new List<LoggingMatrix>();
|
||||||
|
_mockLoggingMatrixService.Setup(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(),
|
||||||
|
It.IsAny<string>(),
|
||||||
|
It.IsAny<string>())).ReturnsAsync(testLoggingMatrix);
|
||||||
|
|
||||||
|
var eventLogResult = new EventLog
|
||||||
|
{
|
||||||
|
EventLogId = 1,
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = null
|
||||||
|
};
|
||||||
|
_mockEventLogRepository.Setup(x => x.AddAsync(It.IsAny<EventLog>())).ReturnsAsync(eventLogResult);
|
||||||
|
_mockDebugEventLogService.Setup(x => x.DebugEventLog(It.IsAny<EventLog>()));
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await _eventLogService.HandleIncomingEventLog(testEventLog);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
|
_mockEventLogRepository.Verify(x => x.AddAsync(It.IsAny<EventLog>()), Times.Never);
|
||||||
|
_mockDebugEventLogService.Verify(x => x.DebugEventLog(It.IsAny<EventLog>()), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleEventLog_NoMatrixFound_EventLogNotSaved_DebugSaved()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testEventLog = new EventLog()
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
};
|
||||||
|
|
||||||
|
var testLoggingMatrix = new List<LoggingMatrix>();
|
||||||
|
_mockLoggingMatrixService.Setup(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(),
|
||||||
|
It.IsAny<string>(),
|
||||||
|
It.IsAny<string>())).ReturnsAsync(testLoggingMatrix);
|
||||||
|
|
||||||
|
var eventLogResult = new EventLog
|
||||||
|
{
|
||||||
|
EventLogId = 1,
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2020"),
|
||||||
|
Message = "Test Message",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
};
|
||||||
|
_mockEventLogRepository.Setup(x => x.AddAsync(It.IsAny<EventLog>())).ReturnsAsync(eventLogResult);
|
||||||
|
_mockDebugEventLogService.Setup(x => x.DebugEventLog(It.IsAny<EventLog>()));
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await _eventLogService.HandleIncomingEventLog(testEventLog);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetByApplicationLevelAndGroupAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
|
_mockEventLogRepository.Verify(x => x.AddAsync(It.IsAny<EventLog>()), Times.Never);
|
||||||
|
_mockDebugEventLogService.Verify(x => x.DebugEventLog(It.IsAny<EventLog>()), Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ServiceTests;
|
||||||
|
|
||||||
|
public class LogDistributionServiceTest
|
||||||
|
{
|
||||||
|
private LogDistributionService _logDistributionService;
|
||||||
|
private readonly Mock<IEventLogService> _mockEventLogService;
|
||||||
|
private readonly Mock<ILoggingMatrixService> _mockLoggingMatrixService;
|
||||||
|
private readonly Mock<INotificationsApiService> _notificationsApiService;
|
||||||
|
|
||||||
|
public LogDistributionServiceTest()
|
||||||
|
{
|
||||||
|
_mockEventLogService = new Mock<IEventLogService>();
|
||||||
|
_mockLoggingMatrixService = new Mock<ILoggingMatrixService>();
|
||||||
|
_notificationsApiService = new Mock<INotificationsApiService>();
|
||||||
|
|
||||||
|
_logDistributionService = new LogDistributionService(_mockEventLogService.Object,
|
||||||
|
_mockLoggingMatrixService.Object,
|
||||||
|
_notificationsApiService.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleLogDistribution_NoEventLogs()
|
||||||
|
{
|
||||||
|
var eventLogs = new List<EventLog>();
|
||||||
|
_mockEventLogService.Setup(x => x.GetAsync()).ReturnsAsync(eventLogs);
|
||||||
|
|
||||||
|
await _logDistributionService.HandleLogDistribution();
|
||||||
|
|
||||||
|
_mockEventLogService.Verify(x => x.GetAsync(), Times.Once);
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetActiveAsync(), Times.Never);
|
||||||
|
_notificationsApiService.Verify(x => x.SendNotificationAsync(It.IsAny<LoggingMatrix>(), It.IsAny<List<EventLog>>()), Times.Never);
|
||||||
|
_mockEventLogService.Verify(x => x.DeleteMany(It.IsAny<List<EventLog>>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleLogDistribution_EventLogs_NoMatrix()
|
||||||
|
{
|
||||||
|
var eventLogs = new List<EventLog>
|
||||||
|
{
|
||||||
|
new EventLog
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2022"),
|
||||||
|
Message = "Test Message 1",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
},
|
||||||
|
new EventLog
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2022"),
|
||||||
|
Message = "Test Message 2",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_mockEventLogService.Setup(x => x.GetAsync()).ReturnsAsync(eventLogs);
|
||||||
|
|
||||||
|
var loggingMatrixs = new List<LoggingMatrix>();
|
||||||
|
_mockLoggingMatrixService.Setup(x => x.GetActiveAsync()).ReturnsAsync(loggingMatrixs);
|
||||||
|
|
||||||
|
await _logDistributionService.HandleLogDistribution();
|
||||||
|
|
||||||
|
_mockEventLogService.Verify(x => x.GetAsync(), Times.Once);
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetActiveAsync(), Times.Once);
|
||||||
|
_notificationsApiService.Verify(x => x.SendNotificationAsync(It.IsAny<LoggingMatrix>(), It.IsAny<List<EventLog>>()), Times.Never);
|
||||||
|
_mockEventLogService.Verify(x => x.DeleteMany(It.IsAny<List<EventLog>>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleLogDistribution_EventLogs_LoggingMatrix_SendEmail()
|
||||||
|
{
|
||||||
|
var eventLogs = new List<EventLog>
|
||||||
|
{
|
||||||
|
new EventLog
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2022"),
|
||||||
|
Message = "Test Message 1",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
},
|
||||||
|
new EventLog
|
||||||
|
{
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
LogTimeStamp = Convert.ToDateTime("1/1/2022"),
|
||||||
|
Message = "Test Message 2",
|
||||||
|
Environment = "Test",
|
||||||
|
DebugData = "Test Debug Data"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_mockEventLogService.Setup(x => x.GetAsync()).ReturnsAsync(eventLogs);
|
||||||
|
|
||||||
|
var loggingMatrixs = new List<LoggingMatrix>
|
||||||
|
{
|
||||||
|
new LoggingMatrix
|
||||||
|
{
|
||||||
|
LoggingMatrixId = 1,
|
||||||
|
Application = "Test App",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
Email = "[email protected]",
|
||||||
|
Disabled = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_mockLoggingMatrixService.Setup(x => x.GetActiveAsync()).ReturnsAsync(loggingMatrixs);
|
||||||
|
|
||||||
|
await _logDistributionService.HandleLogDistribution();
|
||||||
|
|
||||||
|
_mockEventLogService.Verify(x => x.GetAsync(), Times.Once);
|
||||||
|
_mockLoggingMatrixService.Verify(x => x.GetActiveAsync(), Times.Once);
|
||||||
|
_notificationsApiService.Verify(x => x.SendNotificationAsync(It.IsAny<LoggingMatrix>(), It.IsAny<List<EventLog>>()), Times.Once);
|
||||||
|
_mockEventLogService.Verify(x => x.DeleteMany(It.IsAny<List<EventLog>>()), Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Exceptions;
|
||||||
|
using LCU.Api.Internal.MaidBotApi.Services;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Models;
|
||||||
|
using LCU.Api.Internal.MaidBotLib.Repositories;
|
||||||
|
using LCU.Library.Internal.Exceptions;
|
||||||
|
|
||||||
|
namespace LCU.Api.Internal.MaidBotTests.ServiceTests;
|
||||||
|
|
||||||
|
public class LoggingMatrixServiceTest
|
||||||
|
{
|
||||||
|
private readonly LoggingMatrixService _loggingMatrixService;
|
||||||
|
private readonly Mock<ILoggingMatrixRepository> _mockLoggingMatrixRepository;
|
||||||
|
|
||||||
|
public LoggingMatrixServiceTest()
|
||||||
|
{
|
||||||
|
var mockUnitOfWork = new Mock<IUnitOfWork>();
|
||||||
|
_mockLoggingMatrixRepository = new Mock<ILoggingMatrixRepository>();
|
||||||
|
_loggingMatrixService = new LoggingMatrixService(mockUnitOfWork.Object, _mockLoggingMatrixRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAsync_Success()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixRepository.Setup(repo => repo.ListAsync()).ReturnsAsync(new List<LoggingMatrix>()
|
||||||
|
{
|
||||||
|
new LoggingMatrix(),
|
||||||
|
new LoggingMatrix()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixService.GetAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Equal(2, result.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAsync_Exception_Throws_ServerError()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixRepository.Setup(repo => repo.ListAsync()).ThrowsAsync(new Exception());
|
||||||
|
|
||||||
|
// Act / Assert
|
||||||
|
await Assert.ThrowsAsync<ServiceException>(async () => await _loggingMatrixService.GetAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SaveAsync_Success()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixRepository.Setup(repo => repo.AddAsync(It.IsAny<LoggingMatrix>())).ReturnsAsync(new LoggingMatrix());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixService.SaveAsync(new LoggingMatrix());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SaveAsync_Exception_Throws_ServerError()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_mockLoggingMatrixRepository.Setup(repo => repo.AddAsync(It.IsAny<LoggingMatrix>())).ThrowsAsync(new Exception());
|
||||||
|
|
||||||
|
// Act / Assert
|
||||||
|
await Assert.ThrowsAsync<ServiceException>(async () =>
|
||||||
|
await _loggingMatrixService.SaveAsync(new LoggingMatrix()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateAsync_Success_Updates_Fields()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testingLoggingMatrix = new LoggingMatrix()
|
||||||
|
{
|
||||||
|
LoggingMatrixId = 1,
|
||||||
|
Application = "Test Application",
|
||||||
|
Level = "Test Level",
|
||||||
|
Group = "Test Group",
|
||||||
|
Email = "[email protected]",
|
||||||
|
Disabled = false
|
||||||
|
};
|
||||||
|
_mockLoggingMatrixRepository.Setup(repo => repo.FindByIdAsync(It.IsAny<int>())).ReturnsAsync(testingLoggingMatrix);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _loggingMatrixService.UpdateAsync(testingLoggingMatrix);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.Equal(testingLoggingMatrix.LoggingMatrixId, result.LoggingMatrixId);
|
||||||
|
Assert.Equal(testingLoggingMatrix.Application, result.Application);
|
||||||
|
Assert.Equal(testingLoggingMatrix.Level, result.Level);
|
||||||
|
Assert.Equal(testingLoggingMatrix.Group, result.Group);
|
||||||
|
Assert.Equal(testingLoggingMatrix.Email, result.Email);
|
||||||
|
Assert.Equal(testingLoggingMatrix.Disabled, result.Disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!-- additional settings used during the dotnet test execution step in the azure dev ops pipeline -->
|
||||||
|
|
||||||
|
<RunSettings>
|
||||||
|
|
||||||
|
<DataCollectionRunSettings>
|
||||||
|
<DataCollectors>
|
||||||
|
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<Configuration>
|
||||||
|
<CodeCoverage>
|
||||||
|
|
||||||
|
|
||||||
|
<CompanyNames>
|
||||||
|
<Exclude>
|
||||||
|
<CompanyName>.*microsoft.*</CompanyName>
|
||||||
|
</Exclude>
|
||||||
|
</CompanyNames>
|
||||||
|
|
||||||
|
</CodeCoverage>
|
||||||
|
</Configuration>
|
||||||
|
</DataCollector>
|
||||||
|
|
||||||
|
</DataCollectors>
|
||||||
|
</DataCollectionRunSettings>
|
||||||
|
|
||||||
|
</RunSettings>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Introduction
|
||||||
|
Maidbot was created to give us the ability to get notifications on seq and other loggings. It has an api endpoint that can be used to queue a log. Once the log is consumed it queries our LoggingMatrix for the Application, Level, and Group. If a matrix is found the email is used to send a notification with the message of the log.
|
||||||
|
|
||||||
|
# Seq Debugging
|
||||||
|
Since seq app can only be tested on seq, there is no way to debug locally. This adds a pain to testing the application. So if there is a need to test follow the following steps.
|
||||||
|
|
||||||
|
Local MaidBotApi Steps.
|
||||||
|
1. Create your own test queue in QA Rabbit. Use the same exchange LCU.Logging.Direct and routing key for binding.
|
||||||
|
2. Change appsettings to use your test queue.
|
||||||
|
|
||||||
|
Seq App Steps
|
||||||
|
1. Make code adjustments to SeqToRabbit.
|
||||||
|
2. Build
|
||||||
|
3. Grab nuget package from bin.
|
||||||
|
4. Change name of nuget to indicate it is for debugging.
|
||||||
|
5. Go to QA server and to the seq nuget folder. (Currently C:\Program Files\Seq\Nuget)
|
||||||
|
6. Add nuget file
|
||||||
|
7. Go to QA seq --> settings --> Apps --> Install From Nuget
|
||||||
|
8. Select "LocalMachine" as Feed.
|
||||||
|
9. Add your test nuget package name and put as Package Id. (Doesn't require package version).
|
||||||
|
10. Install.
|
||||||
|
11. Add Instance
|
||||||
|
12. Create a Title that indicates that it is Debuging/Testing.
|
||||||
|
13. Add Stream that you wish to use to test. NOTE: Do not use information or other logging that occurs very frequently. If there is an issue with your app it will flood seq with errors.
|
||||||
|
14. Add QA MaidBotApi url
|
||||||
|
15. Select DebugMode to indicate that the raw log will be saved to our MaidBot DebugEventLog table.
|
||||||
|
16. DO NOT select "Run the app on existing events" as this can cause a flood logs. (Unless fully aware what you are pulling in).
|
||||||
|
17. Save Changes
|
||||||
|
|
||||||
|
|
||||||
|
#App Integration Steps
|
||||||
|
- Pull LCU.Api.Internal.MaidBotLib Nuget into project.
|
||||||
|
- Add Context of desired property such as Group.
|
||||||
|
- Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group),
|
||||||
|
Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment))
|
||||||
|
.Fatal("Failure return status, message: {0} {1}", e.Message, e.StackTrace);
|
||||||
|
- Use MaidBotApi swagger to create matrix to follow your app, desired level, and group.
|
||||||
|
- In Seq create signal that will capture this log(If not already created).
|
||||||
|
- Create instance that will watch this signal.
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
parameters:
|
||||||
|
- name: target_environment
|
||||||
|
displayName: Target Environment
|
||||||
|
type: string
|
||||||
|
default: qa
|
||||||
|
values:
|
||||||
|
- qa
|
||||||
|
- uat
|
||||||
|
- prd
|
||||||
|
- name: k8s_namespace
|
||||||
|
displayName: K8s Namespace to deploy to
|
||||||
|
type: string
|
||||||
|
default: landmarkcu
|
||||||
|
values:
|
||||||
|
- landmarkcu
|
||||||
|
|
||||||
|
variables:
|
||||||
|
- template: ./config-files/${{ parameters.target_environment }}-pvars.yaml
|
||||||
|
- name: source_branch_name
|
||||||
|
value: $[replace(replace(variables['Build.SourceBranch'], 'refs/heads/', ''), '/', '-')]
|
||||||
|
- name: docker_container_repository_name
|
||||||
|
value: landmarkcu/lcu.api.internal.maidbot-maidbot
|
||||||
|
|
||||||
|
resources:
|
||||||
|
repositories:
|
||||||
|
- repository: azdo_pipeline_templates
|
||||||
|
type: git
|
||||||
|
name: Infrastructure Platform/azdo-pipeline-templates
|
||||||
|
ref: main
|
||||||
|
|
||||||
|
stages:
|
||||||
|
# DOTNET BUILD AND NUGET PUSH
|
||||||
|
- template: dotnet-nuget-build-push.yaml@azdo_pipeline_templates
|
||||||
|
parameters:
|
||||||
|
azdo_agent_pool: $(pvar_azdo_agent_pool_nuget)
|
||||||
|
azure_artifacts_feed: 'LCU-Internal'
|
||||||
|
branches_to_push:
|
||||||
|
- develop
|
||||||
|
- main
|
||||||
|
|
||||||
|
# DACPAC BUILD AND PUSH
|
||||||
|
- template: db-build-deploy.yaml@azdo_pipeline_templates
|
||||||
|
parameters:
|
||||||
|
azdo_agent_pool: $(pvar_azdo_agent_pool_db)
|
||||||
|
azdo_deployment_environment: $(pvar_azdo_deployment_environment_db)
|
||||||
|
sql_project_path: './LCU.API.Internal.MaidBotSql/LCU.API.Internal.MaidBotSql.sqlproj'
|
||||||
|
built_sql_dacpac_file_path: './LCU.API.Internal.MaidBotSql/bin/Release/LCU.API.Internal.MaidBotSql.dacpac'
|
||||||
|
name_of_artifact: LCU_API_Internal_MaidBotSql_dacpac
|
||||||
|
db_name: $(pvar_LCU_Api_Internal_MaidBotSql_db_name)
|
||||||
|
sql_server_name: $(pvar_LCU_Api_Internal_MaidBotSql_sql_server_name)
|
||||||
|
|
||||||
|
# DOCKER BUILD AND PUSH
|
||||||
|
- template: docker-build-push.yaml@azdo_pipeline_templates
|
||||||
|
parameters:
|
||||||
|
azdo_agent_pool: $(pvar_azdo_agent_pool)
|
||||||
|
docker_registry_service_connection: $(pvar_docker_registry_service_connection)
|
||||||
|
docker_container_repository_name: $(docker_container_repository_name)
|
||||||
|
dockerfile_path: ./Dockerfile
|
||||||
|
docker_image_tags: |
|
||||||
|
build-$(Build.BuildId)
|
||||||
|
$(source_branch_name)
|
||||||
|
|
||||||
|
# K8S DEPLOY
|
||||||
|
- template: k8s-deploy.yaml@azdo_pipeline_templates
|
||||||
|
parameters:
|
||||||
|
dependsOn: CI
|
||||||
|
condition: or(eq(variables['Build.SourceBranchName'], 'develop'), eq(variables['Build.SourceBranchName'], 'main'))
|
||||||
|
azdo_agent_pool: $(pvar_azdo_agent_pool)
|
||||||
|
kubectl_version: $(pvar_kubectl_version)
|
||||||
|
k8s_service_connection: $(pvar_k8s_service_connection)
|
||||||
|
k8s_namespace: ${{ parameters.k8s_namespace }}
|
||||||
|
k8s_kustomization_path: ./kustomize/overlays/${{ parameters.target_environment }}
|
||||||
|
docker_registry_service_connection: $(pvar_docker_registry_service_connection)
|
||||||
|
docker_image_to_deploy: $(docker_container_repository_name):build-$(Build.BuildId)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- '*'
|
||||||
|
exclude:
|
||||||
|
- 'main'
|
||||||
|
- 'develop'
|
||||||
|
extends:
|
||||||
|
template: azure-k8s-pipeline.yaml
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- 'main'
|
||||||
|
extends:
|
||||||
|
template: azure-k8s-pipeline.yaml
|
||||||
|
parameters:
|
||||||
|
target_environment: prd
|
||||||
|
k8s_namespace: landmarkcu
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- 'develop'
|
||||||
|
extends:
|
||||||
|
template: azure-k8s-pipeline.yaml
|
||||||
|
parameters:
|
||||||
|
target_environment: qa
|
||||||
|
k8s_namespace: landmarkcu
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- 'main'
|
||||||
|
extends:
|
||||||
|
template: azure-k8s-pipeline.yaml
|
||||||
|
parameters:
|
||||||
|
target_environment: uat
|
||||||
|
k8s_namespace: landmarkcu
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
variables:
|
||||||
|
pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-prd-lz-uscz
|
||||||
|
pvar_docker_registry_service_connection: Docker Registry LMCU
|
||||||
|
pvar_k8s_service_connection: svcon-sub-df-lcu-apps-prd-aks-k8s-uscz
|
||||||
|
pvar_kubectl_version: 1.25.9
|
||||||
|
pvar_azdo_agent_pool_nuget: LCUOnPrem
|
||||||
|
pvar_azdo_agent_pool_db: LCUOnPrem
|
||||||
|
pvar_azdo_deployment_environment_db: DB-PRD
|
||||||
|
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_db_name: MaidBot
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_sql_server_name: D1CLS01P
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
variables:
|
||||||
|
pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-qa-lz-uscz
|
||||||
|
pvar_docker_registry_service_connection: Docker Registry LMCU
|
||||||
|
pvar_k8s_service_connection: svcon-sub-df-lcu-apps-qa-aks-k8s-uscz
|
||||||
|
pvar_kubectl_version: 1.25.9
|
||||||
|
pvar_azdo_agent_pool_nuget: LCUOnPrem
|
||||||
|
pvar_azdo_agent_pool_db: LCUOnPrem
|
||||||
|
pvar_azdo_deployment_environment_db: DB-QA
|
||||||
|
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_db_name: MaidBot
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_sql_server_name: DAZCDTBWEB01Q
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
variables:
|
||||||
|
pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-uat-lz-uscz
|
||||||
|
pvar_docker_registry_service_connection: Docker Registry LMCU
|
||||||
|
pvar_k8s_service_connection: svcon-sub-df-lcu-apps-uat-aks-k8s-uscz
|
||||||
|
pvar_kubectl_version: 1.25.9
|
||||||
|
pvar_azdo_agent_pool_nuget: LCUOnPrem
|
||||||
|
pvar_azdo_agent_pool_db: LCUOnPrem
|
||||||
|
pvar_azdo_deployment_environment_db: DB-UAT
|
||||||
|
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_db_name: MaidBot
|
||||||
|
pvar_LCU_Api_Internal_MaidBotSql_sql_server_name: D1CLS01U
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# ASP.NET Core
|
||||||
|
|
||||||
|
name: 'MaidBotAPI.$(Build.SourceBranchName).$(Date:yyyyMMdd)$(Rev:.r)'
|
||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
pool:
|
||||||
|
name: LCUOnPrem
|
||||||
|
|
||||||
|
variables:
|
||||||
|
buildConfiguration: 'Release'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
inputs:
|
||||||
|
command: 'restore'
|
||||||
|
feedsToUse: 'select'
|
||||||
|
vstsFeed: '58ebbac4-8e98-4281-bb3f-58003852f4a7'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
inputs:
|
||||||
|
command: 'build'
|
||||||
|
projects: '**/*.csproj'
|
||||||
|
arguments: '--configuration $(buildConfiguration)'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: Test
|
||||||
|
inputs:
|
||||||
|
command: test
|
||||||
|
projects: '**/*.Tests.csproj'
|
||||||
|
arguments: '--configuration $(BuildConfiguration) --collect "Code coverage" --settings additional_test_args.runsettings'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'dotnet publish $(buildConfiguration)'
|
||||||
|
inputs:
|
||||||
|
command: 'publish'
|
||||||
|
publishWebProjects: false
|
||||||
|
projects: '**/*.csproj'
|
||||||
|
arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
|
||||||
|
|
||||||
|
- task: CopyFiles@2
|
||||||
|
displayName: Copy Nuget Package to artifact staging directory
|
||||||
|
inputs:
|
||||||
|
SourceFolder: './LCU.Api.Internal.MaidBotSeqApp/bin/$(BuildConfiguration)/'
|
||||||
|
Contents: '*.nupkg'
|
||||||
|
TargetFolder: '$(build.artifactstagingdirectory)'
|
||||||
|
OverWrite: true
|
||||||
|
|
||||||
|
- task: NuGetCommand@2
|
||||||
|
condition: and (succeeded(), or( eq(variables['Build.SourceBranchName'], 'develop'), eq(variables['Build.SourceBranchName'], 'main')) )
|
||||||
|
displayName: 'NuGet push'
|
||||||
|
inputs:
|
||||||
|
command: push
|
||||||
|
packagesToPush: 'LCU.Api.Internal.MaidBotLib/bin/Release/*.nupkg'
|
||||||
|
publishVstsFeed: '58ebbac4-8e98-4281-bb3f-58003852f4a7'
|
||||||
|
allowPackageConflicts: true
|
||||||
|
|
||||||
|
- task: MSBuild@1
|
||||||
|
displayName: Build sql project
|
||||||
|
inputs:
|
||||||
|
solution: './LCU.Api.Internal.MaidBotSql/LCU.Api.Internal.MaidBotSql.sqlproj'
|
||||||
|
configuration: 'Release'
|
||||||
|
|
||||||
|
- task: CopyFiles@2
|
||||||
|
displayName: Copy dacpac to artifact staging directory
|
||||||
|
inputs:
|
||||||
|
SourceFolder: './LCU.Api.Internal.MaidBotSql/bin/$(BuildConfiguration)/'
|
||||||
|
Contents: 'LCU.Api.Internal.MaidBotSql.dacpac'
|
||||||
|
TargetFolder: '$(build.artifactstagingdirectory)'
|
||||||
|
OverWrite: true
|
||||||
|
|
||||||
|
- task: PublishBuildArtifacts@1
|
||||||
|
condition: and (succeeded(), or( eq(variables['Build.SourceBranchName'], 'develop'), eq(variables['Build.SourceBranchName'], 'main')) )
|
||||||
|
displayName: 'Publish Artifact: dist'
|
||||||
|
inputs:
|
||||||
|
PathtoPublish: '$(build.artifactstagingdirectory)'
|
||||||
|
ArtifactName: 'dist'
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: maidbot-api
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 25%
|
||||||
|
maxUnavailable: 25%
|
||||||
|
type: RollingUpdate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: maidbot-api
|
||||||
|
spec:
|
||||||
|
volumes: []
|
||||||
|
containers:
|
||||||
|
- name: maidbot-api
|
||||||
|
env: []
|
||||||
|
volumeMounts: []
|
||||||
|
image: maidbot-api
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
memory: 512Mi
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
httpGet:
|
||||||
|
path: /api/status
|
||||||
|
port: 8080
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
httpGet:
|
||||||
|
path: /api/status
|
||||||
|
port: 8080
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: maidbot-api
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
targetPort: 8080
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
resources:
|
||||||
|
- Deployment.yaml
|
||||||
|
- Service.yaml
|
||||||
|
- virtual-service.yaml
|
||||||
|
- secrets-provider-class.yaml
|
||||||
|
|
||||||
|
images:
|
||||||
|
- name: maidbot-api
|
||||||
|
newName: landmarkcu/lcu.api.internal.maidbot-maidbot
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
apiVersion: secrets-store.csi.x-k8s.io/v1
|
||||||
|
kind: SecretProviderClass
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api-csi-key-vault-secrets-provider
|
||||||
|
spec:
|
||||||
|
provider: azure
|
||||||
|
parameters:
|
||||||
|
usePodIdentity: "false"
|
||||||
|
useVMManagedIdentity: "true"
|
||||||
|
tenantId: 63cd1554-2783-4a86-ae50-b9e6c21c9499
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1beta1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api
|
||||||
|
spec:
|
||||||
|
hosts: []
|
||||||
|
gateways:
|
||||||
|
- istio-system/ingress-gateway
|
||||||
|
http:
|
||||||
|
- name: maidbot-api
|
||||||
|
match:
|
||||||
|
- uri:
|
||||||
|
prefix: /
|
||||||
|
route:
|
||||||
|
- destination:
|
||||||
|
host: maidbot-api
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
path: set_secrets_deployment.yaml
|
||||||
|
- target:
|
||||||
|
kind: SecretProviderClass
|
||||||
|
path: set_secrets_provider.yaml
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/volumes/-
|
||||||
|
value:
|
||||||
|
name: maidbot-api-secrets
|
||||||
|
csi:
|
||||||
|
driver: secrets-store.csi.k8s.io
|
||||||
|
readOnly: true
|
||||||
|
volumeAttributes:
|
||||||
|
secretProviderClass: normal-maidbot-api-csi-key-vault-secrets-provider
|
||||||
|
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||||
|
value:
|
||||||
|
name: maidbot-api-secrets
|
||||||
|
mountPath: /vault/secrets/maidbot-api-seq-api-key.json
|
||||||
|
readOnly: true
|
||||||
|
subPath: maidbot-api-seq-api-key
|
||||||
|
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||||
|
value:
|
||||||
|
name: maidbot-api-secrets
|
||||||
|
mountPath: /vault/secrets/maidbot-api-connection-configuration-password.json
|
||||||
|
readOnly: true
|
||||||
|
subPath: maidbot-api-connection-configuration-password
|
||||||
|
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||||
|
value:
|
||||||
|
name: maidbot-api-secrets
|
||||||
|
mountPath: /vault/secrets/maidbot-api-connection-configuration-username.json
|
||||||
|
readOnly: true
|
||||||
|
subPath: maidbot-api-connection-configuration-username
|
||||||
|
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||||
|
value:
|
||||||
|
name: maidbot-api-secrets
|
||||||
|
mountPath: /vault/secrets/maidbot-database-connection.json
|
||||||
|
readOnly: true
|
||||||
|
subPath: maidbot-database-connection
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
- op: add
|
||||||
|
path: /spec/parameters/objects
|
||||||
|
value: |
|
||||||
|
array:
|
||||||
|
- |
|
||||||
|
objectName: maidbot-api-seq-api-key
|
||||||
|
objectType: secret
|
||||||
|
objectVersion: ""
|
||||||
|
- |
|
||||||
|
objectName: maidbot-api-connection-configuration-password
|
||||||
|
objectType: secret
|
||||||
|
objectVersion: ""
|
||||||
|
- |
|
||||||
|
objectName: maidbot-api-connection-configuration-username
|
||||||
|
objectType: secret
|
||||||
|
objectVersion: ""
|
||||||
|
- |
|
||||||
|
objectName: maidbot-database-connection
|
||||||
|
objectType: secret
|
||||||
|
objectVersion: ""
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
|
||||||
|
#Test istio process
|
||||||
|
namePrefix: normal-
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- name: maidbot-api-appsettings
|
||||||
|
files:
|
||||||
|
- appsettings/appsettings.json
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
patches:
|
||||||
|
- target:
|
||||||
|
kind: Deployment
|
||||||
|
path: set_appsettings_deployment.yaml
|
||||||
|
|
||||||
|
replacements:
|
||||||
|
- source:
|
||||||
|
kind: Deployment
|
||||||
|
fieldPath: metadata.name
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
kind: Deployment
|
||||||
|
fieldPaths:
|
||||||
|
- spec.selector.matchLabels.app
|
||||||
|
- spec.template.metadata.labels.app
|
||||||
|
- spec.template.spec.containers.*.name
|
||||||
|
|
||||||
|
- select:
|
||||||
|
kind: Service
|
||||||
|
fieldPaths:
|
||||||
|
- spec.selector.app
|
||||||
|
|
||||||
|
- select:
|
||||||
|
kind: VirtualService
|
||||||
|
fieldPaths:
|
||||||
|
- spec.http.*.route.*.destination.host
|
||||||
|
- spec.http.*.name
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/volumes/-
|
||||||
|
value:
|
||||||
|
name: volume-appsettings
|
||||||
|
configMap:
|
||||||
|
name: maidbot-api-appsettings
|
||||||
|
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/0/volumeMounts/-
|
||||||
|
value:
|
||||||
|
name: volume-appsettings
|
||||||
|
mountPath: /app/config/workload-appsettings
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
resources:
|
||||||
|
- ../../../base
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- set_appsettings_deployment.yaml
|
||||||
|
- set_secrets_provider_class.yaml
|
||||||
|
images:
|
||||||
|
- name: maidbot-api
|
||||||
|
newName: landmarkcu/lcu.api.internal.maidbot-maidbot
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: maidbot-api
|
||||||
|
env:
|
||||||
|
- name: ASPNETCORE_ENVIRONMENT
|
||||||
|
value: "Development"
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
apiVersion: secrets-store.csi.x-k8s.io/v1
|
||||||
|
kind: SecretProviderClass
|
||||||
|
metadata:
|
||||||
|
name: maidbot-api-csi-key-vault-secrets-provider
|
||||||
|
spec:
|
||||||
|
parameters:
|
||||||
|
userAssignedIdentityID: 3286ed9a-f85c-4c50-b742-dbd3c1c3fe1f
|
||||||
|
keyvaultName: kv-lz-apps-qa-uscz
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
resources:
|
||||||
|
- normal
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: maidbot-configmap
|
||||||
|
data:
|
||||||
|
primary.json: |
|
||||||
|
{
|
||||||
|
"Primary": {
|
||||||
|
"SeqUrl": "https://qa-seq.lcu-internal.com",
|
||||||
|
"CorsAllowedOrigins": [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"http://lcu-internal.com",
|
||||||
|
"https://lcu-internal.com",
|
||||||
|
"https://qa-api.lcu-internal.com",
|
||||||
|
"https://uat-api.lcu-internal.com",
|
||||||
|
"https://api.lcu-internal.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
resources:
|
||||||
|
- configmap.yaml
|
||||||
|
- ../common
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- set_virtual_service.yaml
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user