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