├── .gitignore ├── LICENSE ├── README.md ├── Resources ├── CatFactory │ └── TheWatcher.EntityModel │ │ ├── Program.cs │ │ ├── TheWatcher.EntityModel.csproj │ │ └── TheWatcher.EntityModel.sln └── Scripts │ └── SQL │ ├── 00-database.sql │ ├── 01-tables.sql │ ├── 02-constraints.sql │ └── deploy.bat └── Source ├── Backend └── TheWatcher │ ├── Seed │ └── TheWatcher.Seed.Db │ │ ├── Helpers │ │ └── DbContextHelper.cs │ │ ├── Program.cs │ │ ├── Seeds │ │ ├── Environment.cs │ │ ├── ResourceCategories.cs │ │ ├── ResourceWatches.cs │ │ ├── Resources.cs │ │ └── Watchers.cs │ │ └── TheWatcher.Seed.Db.csproj │ ├── Source │ ├── TheWatcher.API.Common │ │ ├── CorsSettings.cs │ │ ├── Models │ │ │ ├── Contracts │ │ │ │ ├── IListResponse.cs │ │ │ │ ├── IResponse.cs │ │ │ │ └── ISingleResponse.cs │ │ │ ├── Extensions.cs │ │ │ ├── ListResponse.cs │ │ │ ├── Response.cs │ │ │ └── SingleResponse.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── TheWatcher.API.Common.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── TheWatcher.API.Monitor │ │ ├── Controllers │ │ │ └── MonitorController.cs │ │ ├── HubMethods.cs │ │ ├── Hubs │ │ │ ├── Models │ │ │ │ └── ResourceWatchArg.cs │ │ │ └── MonitorHub.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Services │ │ │ ├── Models │ │ │ │ └── ResourceWatchItemModel.cs │ │ │ └── MonitorService.cs │ │ ├── TheWatcher.API.Monitor.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── TheWatcher.API.Panel │ │ ├── Controllers │ │ │ └── PanelController.cs │ │ ├── Models │ │ │ ├── ResourceDetailsModel.cs │ │ │ ├── ResourceWatchDetailsModel.cs │ │ │ ├── ResourceWatchParameterDetailsModel.cs │ │ │ ├── WatcherDetailsModel.cs │ │ │ └── WatcherParameterDetailsModel.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── TheWatcher.API.Panel.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── TheWatcher.Domain.Core │ │ ├── Common │ │ │ ├── Entity.cs │ │ │ └── IEntity.cs │ │ ├── Configurations │ │ │ ├── Common │ │ │ │ └── EntityConfiguration.cs │ │ │ ├── EnvironmentConfiguration.cs │ │ │ ├── ResourceCategoryConfiguration.cs │ │ │ ├── ResourceConfiguration.cs │ │ │ ├── ResourceWatchConfiguration.cs │ │ │ ├── ResourceWatchLogConfiguration.cs │ │ │ ├── ResourceWatchParameterConfiguration.cs │ │ │ ├── WatcherConfiguration.cs │ │ │ └── WatcherParameterConfiguration.cs │ │ ├── Models │ │ │ ├── Environment.cs │ │ │ ├── Resource.cs │ │ │ ├── ResourceCategory.cs │ │ │ ├── ResourceWatch.cs │ │ │ ├── ResourceWatchLog.cs │ │ │ ├── ResourceWatchParameter.cs │ │ │ ├── Watcher.cs │ │ │ └── WatcherParameter.cs │ │ ├── QueryModels │ │ │ ├── ResourceQueryModel.cs │ │ │ ├── ResourceWatchQueryModel.cs │ │ │ └── WatcherQueryModel.cs │ │ ├── TheWatcher.Domain.Core.csproj │ │ ├── TheWatcherDbContext.cs │ │ └── TheWatcherDbContextQueries.cs │ └── TheWatcher.Library.Core │ │ ├── Contracts │ │ ├── IWatcher.cs │ │ └── IWatcherResult.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── TheWatcher.Library.Core.csproj │ │ ├── WatcherParam.cs │ │ └── WatcherResult.cs │ ├── TheWatcher.sln │ └── Watchers │ ├── TheWatcher.Watchers.MongoDB │ ├── MongoDBWatcher.cs │ └── TheWatcher.Watchers.MongoDB.csproj │ ├── TheWatcher.Watchers.PingWatcher │ ├── PingWatcher.cs │ └── TheWatcher.Watchers.PingWatcher.csproj │ ├── TheWatcher.Watchers.PostgreSQL │ ├── PostgreSQLDatabaseWatcher.cs │ └── TheWatcher.Watchers.PostgreSQL.csproj │ ├── TheWatcher.Watchers.RESTfulGet │ ├── RESTfulGetWatcher.cs │ └── TheWatcher.Watchers.RESTfulGet.csproj │ ├── TheWatcher.Watchers.RabbitMQ │ ├── RabbitMQWatcher.cs │ └── TheWatcher.Watchers.RabbitMQ.csproj │ └── TheWatcher.Watchers.SqlServer │ ├── SqlServerDatabaseWatcher.cs │ └── TheWatcher.Watchers.SqlServer.csproj └── Frontend └── thewatcher-gui ├── .editorconfig ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── tasks.json ├── README.md ├── angular.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── components │ │ ├── home │ │ │ ├── home.component.css │ │ │ ├── home.component.html │ │ │ └── home.component.ts │ │ ├── resource-list │ │ │ ├── resource-list-datasource.ts │ │ │ ├── resource-list.component.css │ │ │ ├── resource-list.component.html │ │ │ └── resource-list.component.ts │ │ └── watcher-list │ │ │ ├── watcher-list-datasource.ts │ │ │ ├── watcher-list.component.css │ │ │ ├── watcher-list.component.html │ │ │ └── watcher-list.component.ts │ └── services │ │ ├── common.ts │ │ ├── monitor-client.service.ts │ │ └── panel-client.service.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── settings.ts ├── styles.css └── test.ts ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 HH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ServiceMonitor.NetCore 2 | 3 | This is the stack for this solution: 4 | 5 | .NET Core 6 | Entity Framework Core 7 | ASP.NET Core 8 | 9 | You can read more details about this project in [`this link`](https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core). 10 | 11 | ## Running Solution 12 | 13 | Run *ServiceMonitor.WebAPI* project, Web API runs on port 10000. 14 | 15 | Run *ServiceMonitor* project, this is a console client for Web API project. 16 | 17 | ## Improvements 18 | 19 | You can check the improvements on **Projects** tab. 20 | -------------------------------------------------------------------------------- /Resources/CatFactory/TheWatcher.EntityModel/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Dynamic; 2 | using CatFactory.EntityFrameworkCore; 3 | using CatFactory.ObjectRelationalMapping; 4 | using CatFactory.SqlServer; 5 | using CatFactory.SqlServer.CodeFactory; 6 | using CatFactory.SqlServer.DatabaseObjectModel; 7 | using CatFactory.SqlServer.ObjectRelationalMapping; 8 | 9 | var db = SqlServerDatabase.CreateWithDefaults("TheWatcher"); 10 | 11 | db.AddDefaultTypeMapFor(typeof(string), "nvarchar"); 12 | db.AddDefaultTypeMapFor(typeof(DateTime), "datetime"); 13 | 14 | // todo: add version? 15 | 16 | var watcher = db 17 | .DefineEntity(new 18 | { 19 | Id = (short)0, 20 | Name = "", 21 | Description = "", 22 | ClassName = "", 23 | ClassGuid = Guid.Empty, 24 | AssemblyQualifiedName = "", 25 | }) 26 | .SetNaming("Watcher") 27 | .SetColumnFor(e => e.Name, length: 100) 28 | .SetColumnFor(e => e.Description, nullable: true) 29 | .SetColumnFor(e => e.ClassName, length: 511) 30 | .SetColumnFor(e => e.AssemblyQualifiedName, length: 511) 31 | .SetIdentity(e => e.Id) 32 | .SetPrimaryKey(e => e.Id) 33 | .AddUnique(e => e.Name) 34 | .AddUnique(e => e.ClassName) 35 | .AddUnique(e => e.ClassGuid) 36 | .AddUnique(e => e.AssemblyQualifiedName) 37 | ; 38 | 39 | var watcherParameter = db 40 | .DefineEntity(new 41 | { 42 | Id = (short)0, 43 | WatcherId = (short)0, 44 | Parameter = "", 45 | Value = "", 46 | IsDefault = false, 47 | Description = "" 48 | }) 49 | .SetNaming("WatcherParameter") 50 | .SetColumnFor(e => e.Parameter, length: 100) 51 | .SetColumnFor(e => e.Value, nullable: true) 52 | .SetColumnFor(e => e.Description, nullable: true) 53 | .SetIdentity(e => e.Id) 54 | .SetPrimaryKey(e => e.Id) 55 | .AddUnique(e => new { e.WatcherId, e.Parameter }) 56 | .AddForeignKey(e => e.WatcherId, watcher.Table) 57 | ; 58 | 59 | var resourceCategory = db 60 | .DefineEntity(new 61 | { 62 | Id = (short)0, 63 | Name = "", 64 | WatcherId = (short)0 65 | }) 66 | .SetNaming("ResourceCategory") 67 | .SetColumnFor(e => e.Name, length: 100) 68 | .SetColumnFor(e => e.WatcherId, nullable: true) 69 | .SetIdentity(e => e.Id) 70 | .SetPrimaryKey(e => e.Id) 71 | .AddUnique(e => e.Name) 72 | .AddForeignKey(e => e.WatcherId, watcher.Table) 73 | ; 74 | 75 | var resource = db 76 | .DefineEntity(new 77 | { 78 | Id = (short)0, 79 | Name = "", 80 | ResourceCategoryId = (short)0 81 | }) 82 | .SetNaming("Resource") 83 | .SetColumnFor(e => e.Name, length: 100, nullable: true) 84 | .SetIdentity(e => e.Id) 85 | .SetPrimaryKey(e => e.Id) 86 | .AddForeignKey(e => e.ResourceCategoryId, resourceCategory.Table) 87 | ; 88 | 89 | var environment = db 90 | .DefineEntity(new 91 | { 92 | Id = (short)0, 93 | Name = "" 94 | }) 95 | .SetNaming("Environment") 96 | .SetColumnFor(e => e.Name, length: 100) 97 | .SetIdentity(e => e.Id) 98 | .SetPrimaryKey(e => e.Id) 99 | .AddUnique(e => e.Name) 100 | ; 101 | 102 | var resourceWatch = db 103 | .DefineEntity(new 104 | { 105 | Id = (short)0, 106 | ResourceId = (short)0, 107 | EnvironmentId = (short)0, 108 | Successful = false, 109 | WatchCount = 0, 110 | LastWatch = DateTime.Now, 111 | Interval = 0, 112 | Description = "" 113 | }) 114 | .SetNaming("ResourceWatch") 115 | .SetColumnFor(e => e.Successful, nullable: true) 116 | .SetColumnFor(e => e.WatchCount, nullable: true) 117 | .SetColumnFor(e => e.LastWatch, nullable: true) 118 | .SetColumnFor(e => e.Description, nullable: true) 119 | .SetIdentity(e => e.Id) 120 | .SetPrimaryKey(e => e.Id) 121 | .AddUnique(e => new { e.ResourceId, e.EnvironmentId }) 122 | .AddForeignKey(e => e.ResourceId, resource.Table) 123 | .AddForeignKey(e => e.EnvironmentId, environment.Table) 124 | ; 125 | 126 | var resourceWatchParameter = db 127 | .DefineEntity(new 128 | { 129 | Id = (short)0, 130 | ResourceWatchId = (short)0, 131 | Parameter = "", 132 | Value = "", 133 | Description = "" 134 | }) 135 | .SetNaming("ResourceWatchParameter") 136 | .SetColumnFor(e => e.Parameter, length: 100) 137 | .SetColumnFor(e => e.Value, nullable: true) 138 | .SetColumnFor(e => e.Description, nullable: true) 139 | .SetIdentity(e => e.Id) 140 | .SetPrimaryKey(e => e.Id) 141 | .AddUnique(e => new { e.ResourceWatchId, e.Parameter }) 142 | .AddForeignKey(e => e.ResourceWatchId, resourceWatch.Table) 143 | ; 144 | 145 | var resourceWatchLog = db 146 | .DefineEntity(new 147 | { 148 | Id = (short)0, 149 | ResourceWatchId = (short)0, 150 | AssemblyQualifiedName = "", 151 | ActionName = "", 152 | Successful = false, 153 | Message = "", 154 | ErrorMessage = "" 155 | }) 156 | .SetNaming("ResourceWatchLog") 157 | .SetColumnFor(e => e.AssemblyQualifiedName, length: 511) 158 | .SetColumnFor(e => e.ActionName, length: 511) 159 | .SetColumnFor(e => e.ErrorMessage, nullable: true) 160 | .SetIdentity(e => e.Id) 161 | .SetPrimaryKey(e => e.Id) 162 | .AddForeignKey(e => e.ResourceWatchId, resourceWatch.Table) 163 | ; 164 | 165 | dynamic importBag = new ExpandoObject(); 166 | 167 | importBag.ExtendedProperties = new List(); 168 | 169 | db.AddColumnForTables(new Column { Name = "Active", Type = "bit", ImportBag = importBag }); 170 | db.AddColumnForTables(new Column { Name = "CreationUser", Type = "nvarchar", Length = 50, ImportBag = importBag }); 171 | db.AddColumnForTables(new Column { Name = "CreationDateTime", Type = "datetime", ImportBag = importBag }); 172 | db.AddColumnForTables(new Column { Name = "LastUpdateUser", Type = "nvarchar", Length = 50, Nullable = true, ImportBag = importBag }); 173 | db.AddColumnForTables(new Column { Name = "LastUpdateDateTime", Type = "datetime", Nullable = true, ImportBag = importBag }); 174 | db.AddColumnForTables(new Column { Name = "Version", Type = "rowversion", Nullable = true, ImportBag = importBag }); 175 | 176 | SqlServerDatabaseScriptCodeBuilder.CreateScript(db, @"C:\Temp\Databases", true, true); 177 | 178 | // Create instance of Entity Framework Core project 179 | var project = EntityFrameworkCoreProject 180 | .CreateForV3x("TheWatcher.Domain.Core", db, @"C:\Temp\TheWatcher.Domain.Core"); 181 | 182 | // Apply settings for Entity Framework Core project 183 | project.GlobalSelection(settings => 184 | { 185 | settings.ForceOverwrite = true; 186 | settings.DeclareNavigationProperties = true; 187 | settings.DeclareNavigationPropertiesAsVirtual = true; 188 | settings.AddConfigurationForForeignKeysInFluentAPI = true; 189 | }); 190 | 191 | // Build features for project, group all entities by schema into a feature 192 | project.BuildFeatures(); 193 | 194 | // Scaffolding =^^= 195 | project 196 | .ScaffoldDomain() 197 | ; 198 | -------------------------------------------------------------------------------- /Resources/CatFactory/TheWatcher.EntityModel/TheWatcher.EntityModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Resources/CatFactory/TheWatcher.EntityModel/TheWatcher.EntityModel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32825.248 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheWatcher.EntityModel", "TheWatcher.EntityModel.csproj", "{221E9994-59EB-40C7-AC69-CE2B2C381915}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {221E9994-59EB-40C7-AC69-CE2B2C381915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {221E9994-59EB-40C7-AC69-CE2B2C381915}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {221E9994-59EB-40C7-AC69-CE2B2C381915}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {221E9994-59EB-40C7-AC69-CE2B2C381915}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {03140B89-F9FC-46DE-94A2-A63637490773} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Resources/Scripts/SQL/00-database.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE [TheWatcher] 2 | GO 3 | -------------------------------------------------------------------------------- /Resources/Scripts/SQL/01-tables.sql: -------------------------------------------------------------------------------- 1 | USE [TheWatcher] 2 | GO 3 | 4 | IF OBJECT_ID('dbo.ResourceWatchLog') IS NOT NULL 5 | DROP TABLE [dbo].[ResourceWatchLog] 6 | GO 7 | 8 | IF OBJECT_ID('dbo.ResourceWatchParameter') IS NOT NULL 9 | DROP TABLE [dbo].[ResourceWatchParameter] 10 | GO 11 | 12 | IF OBJECT_ID('dbo.ResourceWatch') IS NOT NULL 13 | DROP TABLE [dbo].[ResourceWatch] 14 | GO 15 | 16 | IF OBJECT_ID('dbo.Environment') IS NOT NULL 17 | DROP TABLE [dbo].[Environment] 18 | GO 19 | 20 | IF OBJECT_ID('dbo.Resource') IS NOT NULL 21 | DROP TABLE [dbo].[Resource] 22 | GO 23 | 24 | IF OBJECT_ID('dbo.ResourceCategory') IS NOT NULL 25 | DROP TABLE [dbo].[ResourceCategory] 26 | GO 27 | 28 | IF OBJECT_ID('dbo.WatcherParameter') IS NOT NULL 29 | DROP TABLE [dbo].[WatcherParameter] 30 | GO 31 | 32 | IF OBJECT_ID('dbo.Watcher') IS NOT NULL 33 | DROP TABLE [dbo].[Watcher] 34 | GO 35 | 36 | CREATE TABLE [dbo].[Watcher] 37 | ( 38 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 39 | [Name] NVARCHAR(100) NOT NULL, 40 | [Description] NVARCHAR(MAX) NULL, 41 | [ClassName] NVARCHAR(511) NOT NULL, 42 | [ClassGuid] UNIQUEIDENTIFIER NOT NULL, 43 | [AssemblyQualifiedName] NVARCHAR(511) NOT NULL, 44 | [Active] BIT NOT NULL, 45 | [CreationUser] NVARCHAR(50) NOT NULL, 46 | [CreationDateTime] DATETIME NOT NULL, 47 | [LastUpdateUser] NVARCHAR(50) NULL, 48 | [LastUpdateDateTime] DATETIME NULL, 49 | [Version] ROWVERSION NULL 50 | ) 51 | GO 52 | 53 | CREATE TABLE [dbo].[WatcherParameter] 54 | ( 55 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 56 | [WatcherId] SMALLINT NOT NULL, 57 | [Parameter] NVARCHAR(100) NOT NULL, 58 | [Value] NVARCHAR(MAX) NULL, 59 | [IsDefault] BIT NOT NULL, 60 | [Description] NVARCHAR(MAX) NULL, 61 | [Active] BIT NOT NULL, 62 | [CreationUser] NVARCHAR(50) NOT NULL, 63 | [CreationDateTime] DATETIME NOT NULL, 64 | [LastUpdateUser] NVARCHAR(50) NULL, 65 | [LastUpdateDateTime] DATETIME NULL, 66 | [Version] ROWVERSION NULL 67 | ) 68 | GO 69 | 70 | CREATE TABLE [dbo].[ResourceCategory] 71 | ( 72 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 73 | [Name] NVARCHAR(100) NOT NULL, 74 | [WatcherId] SMALLINT NULL, 75 | [Active] BIT NOT NULL, 76 | [CreationUser] NVARCHAR(50) NOT NULL, 77 | [CreationDateTime] DATETIME NOT NULL, 78 | [LastUpdateUser] NVARCHAR(50) NULL, 79 | [LastUpdateDateTime] DATETIME NULL, 80 | [Version] ROWVERSION NULL 81 | ) 82 | GO 83 | 84 | CREATE TABLE [dbo].[Resource] 85 | ( 86 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 87 | [Name] NVARCHAR(100) NULL, 88 | [ResourceCategoryId] SMALLINT NULL, 89 | [Active] BIT NOT NULL, 90 | [CreationUser] NVARCHAR(50) NOT NULL, 91 | [CreationDateTime] DATETIME NOT NULL, 92 | [LastUpdateUser] NVARCHAR(50) NULL, 93 | [LastUpdateDateTime] DATETIME NULL, 94 | [Version] ROWVERSION NULL 95 | ) 96 | GO 97 | 98 | CREATE TABLE [dbo].[Environment] 99 | ( 100 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 101 | [Name] NVARCHAR(100) NOT NULL, 102 | [Active] BIT NOT NULL, 103 | [CreationUser] NVARCHAR(50) NOT NULL, 104 | [CreationDateTime] DATETIME NOT NULL, 105 | [LastUpdateUser] NVARCHAR(50) NULL, 106 | [LastUpdateDateTime] DATETIME NULL, 107 | [Version] ROWVERSION NULL 108 | ) 109 | GO 110 | 111 | CREATE TABLE [dbo].[ResourceWatch] 112 | ( 113 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 114 | [ResourceId] SMALLINT NOT NULL, 115 | [EnvironmentId] SMALLINT NOT NULL, 116 | [Successful] BIT NULL, 117 | [WatchCount] INT NULL, 118 | [LastWatch] DATETIME NULL, 119 | [Interval] INT NOT NULL, 120 | [Description] NVARCHAR(MAX) NULL, 121 | [Active] BIT NOT NULL, 122 | [CreationUser] NVARCHAR(50) NOT NULL, 123 | [CreationDateTime] DATETIME NOT NULL, 124 | [LastUpdateUser] NVARCHAR(50) NULL, 125 | [LastUpdateDateTime] DATETIME NULL, 126 | [Version] ROWVERSION NULL 127 | ) 128 | GO 129 | 130 | CREATE TABLE [dbo].[ResourceWatchParameter] 131 | ( 132 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 133 | [ResourceWatchId] SMALLINT NOT NULL, 134 | [Parameter] NVARCHAR(100) NOT NULL, 135 | [Value] NVARCHAR(MAX) NULL, 136 | [Description] NVARCHAR(MAX) NULL, 137 | [Active] BIT NOT NULL, 138 | [CreationUser] NVARCHAR(50) NOT NULL, 139 | [CreationDateTime] DATETIME NOT NULL, 140 | [LastUpdateUser] NVARCHAR(50) NULL, 141 | [LastUpdateDateTime] DATETIME NULL, 142 | [Version] ROWVERSION NULL 143 | ) 144 | GO 145 | 146 | CREATE TABLE [dbo].[ResourceWatchLog] 147 | ( 148 | [Id] SMALLINT NOT NULL IDENTITY(1, 1), 149 | [ResourceWatchId] SMALLINT NOT NULL, 150 | [AssemblyQualifiedName] NVARCHAR(511) NOT NULL, 151 | [ActionName] NVARCHAR(511) NOT NULL, 152 | [Successful] BIT NOT NULL, 153 | [Message] NVARCHAR(MAX) NOT NULL, 154 | [ErrorMessage] NVARCHAR(MAX) NULL, 155 | [Active] BIT NOT NULL, 156 | [CreationUser] NVARCHAR(50) NOT NULL, 157 | [CreationDateTime] DATETIME NOT NULL, 158 | [LastUpdateUser] NVARCHAR(50) NULL, 159 | [LastUpdateDateTime] DATETIME NULL, 160 | [Version] ROWVERSION NULL 161 | ) 162 | GO 163 | -------------------------------------------------------------------------------- /Resources/Scripts/SQL/02-constraints.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE [dbo].[Watcher] ADD CONSTRAINT [PK_dbo_Watcher] 2 | PRIMARY KEY ([Id]) 3 | GO 4 | 5 | ALTER TABLE [dbo].[Watcher] ADD CONSTRAINT [UQ_dbo_Watcher_Name] 6 | UNIQUE ([Name]) 7 | GO 8 | 9 | ALTER TABLE [dbo].[Watcher] ADD CONSTRAINT [UQ_dbo_Watcher_ClassName] 10 | UNIQUE ([ClassName]) 11 | GO 12 | 13 | ALTER TABLE [dbo].[Watcher] ADD CONSTRAINT [UQ_dbo_Watcher_ClassGuid] 14 | UNIQUE ([ClassGuid]) 15 | GO 16 | 17 | ALTER TABLE [dbo].[Watcher] ADD CONSTRAINT [UQ_dbo_Watcher_AssemblyQualifiedName] 18 | UNIQUE ([AssemblyQualifiedName]) 19 | GO 20 | 21 | ALTER TABLE [dbo].[WatcherParameter] ADD CONSTRAINT [PK_dbo_WatcherParameter] 22 | PRIMARY KEY ([Id]) 23 | GO 24 | 25 | ALTER TABLE [dbo].[WatcherParameter] ADD CONSTRAINT [UQ_dbo_WatcherParameter_WatcherId_Parameter] 26 | UNIQUE ([WatcherId], [Parameter]) 27 | GO 28 | 29 | ALTER TABLE [dbo].[WatcherParameter] ADD CONSTRAINT [FK_dbo_WatcherParameter_WatcherId_dbo_Watcher] 30 | FOREIGN KEY ([WatcherId]) REFERENCES [dbo].[Watcher] 31 | GO 32 | 33 | ALTER TABLE [dbo].[ResourceCategory] ADD CONSTRAINT [PK_dbo_ResourceCategory] 34 | PRIMARY KEY ([Id]) 35 | GO 36 | 37 | ALTER TABLE [dbo].[ResourceCategory] ADD CONSTRAINT [UQ_dbo_ResourceCategory_Name] 38 | UNIQUE ([Name]) 39 | GO 40 | 41 | ALTER TABLE [dbo].[ResourceCategory] ADD CONSTRAINT [FK_dbo_ResourceCategory_WatcherId_dbo_Watcher] 42 | FOREIGN KEY ([WatcherId]) REFERENCES [dbo].[Watcher] 43 | GO 44 | 45 | ALTER TABLE [dbo].[Resource] ADD CONSTRAINT [PK_dbo_Resource] 46 | PRIMARY KEY ([Id]) 47 | GO 48 | 49 | ALTER TABLE [dbo].[Resource] ADD CONSTRAINT [FK_dbo_Resource_ResourceCategoryId_dbo_ResourceCategory] 50 | FOREIGN KEY ([ResourceCategoryId]) REFERENCES [dbo].[ResourceCategory] 51 | GO 52 | 53 | ALTER TABLE [dbo].[Environment] ADD CONSTRAINT [PK_dbo_Environment] 54 | PRIMARY KEY ([Id]) 55 | GO 56 | 57 | ALTER TABLE [dbo].[Environment] ADD CONSTRAINT [UQ_dbo_Environment_Name] 58 | UNIQUE ([Name]) 59 | GO 60 | 61 | ALTER TABLE [dbo].[ResourceWatch] ADD CONSTRAINT [PK_dbo_ResourceWatch] 62 | PRIMARY KEY ([Id]) 63 | GO 64 | 65 | ALTER TABLE [dbo].[ResourceWatch] ADD CONSTRAINT [UQ_dbo_ResourceWatch_ResourceId_EnvironmentId] 66 | UNIQUE ([ResourceId], [EnvironmentId]) 67 | GO 68 | 69 | ALTER TABLE [dbo].[ResourceWatch] ADD CONSTRAINT [FK_dbo_ResourceWatch_ResourceId_dbo_Resource] 70 | FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource] 71 | GO 72 | 73 | ALTER TABLE [dbo].[ResourceWatch] ADD CONSTRAINT [FK_dbo_ResourceWatch_EnvironmentId_dbo_Environment] 74 | FOREIGN KEY ([EnvironmentId]) REFERENCES [dbo].[Environment] 75 | GO 76 | 77 | ALTER TABLE [dbo].[ResourceWatchParameter] ADD CONSTRAINT [PK_dbo_ResourceWatchParameter] 78 | PRIMARY KEY ([Id]) 79 | GO 80 | 81 | ALTER TABLE [dbo].[ResourceWatchParameter] ADD CONSTRAINT [UQ_dbo_ResourceWatchParameter_ResourceWatchId_Parameter] 82 | UNIQUE ([ResourceWatchId], [Parameter]) 83 | GO 84 | 85 | ALTER TABLE [dbo].[ResourceWatchParameter] ADD CONSTRAINT [FK_dbo_ResourceWatchParameter_ResourceWatchId_dbo_ResourceWatch] 86 | FOREIGN KEY ([ResourceWatchId]) REFERENCES [dbo].[ResourceWatch] 87 | GO 88 | 89 | ALTER TABLE [dbo].[ResourceWatchLog] ADD CONSTRAINT [PK_dbo_ResourceWatchLog] 90 | PRIMARY KEY ([Id]) 91 | GO 92 | 93 | ALTER TABLE [dbo].[ResourceWatchLog] ADD CONSTRAINT [FK_dbo_ResourceWatchLog_ResourceWatchId_dbo_ResourceWatch] 94 | FOREIGN KEY ([ResourceWatchId]) REFERENCES [dbo].[ResourceWatch] 95 | GO 96 | -------------------------------------------------------------------------------- /Resources/Scripts/SQL/deploy.bat: -------------------------------------------------------------------------------- 1 | cls 2 | set db_server=(local) 3 | set db_name=TheWatcher 4 | sqlcmd -S %db_server% -d %db_name% -E -i "01-tables.sql" 5 | sqlcmd -S %db_server% -d %db_name% -E -i "02-constraints.sql" 6 | pause 7 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Helpers/DbContextHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using TheWatcher.Domain.Core; 3 | 4 | namespace TheWatcher.Seed.Db.Helpers 5 | { 6 | internal static class DbContextHelper 7 | { 8 | const string ConnectionString = "Server=(local); Database=TheWatcher; Integrated Security=yes; TrustServerCertificate=true;"; 9 | 10 | public static TheWatcherDbContext GetTheWatcherDbContext() 11 | => new(new DbContextOptionsBuilder().UseSqlServer(ConnectionString).Options); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Program.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Seed.Db.Helpers; 2 | using TheWatcher.Seed.Db.Seeds; 3 | 4 | Console.WriteLine("Seeding..."); 5 | Console.WriteLine(); 6 | 7 | using var ctx = DbContextHelper.GetTheWatcherDbContext(); 8 | 9 | var audit = new 10 | { 11 | CreationUser = "thewatcher.seed" 12 | }; 13 | 14 | Console.WriteLine("Creating watchers..."); 15 | 16 | foreach (var tuple in Watchers.Items) 17 | { 18 | var watcher = tuple.Item1; 19 | 20 | watcher.Active = true; 21 | watcher.CreationUser = audit.CreationUser; 22 | watcher.CreationDateTime = DateTime.Now; 23 | 24 | Console.WriteLine($" Adding '{watcher.Name}' watcher..."); 25 | 26 | ctx.Watcher.Add(watcher); 27 | 28 | ctx.SaveChanges(); 29 | 30 | Console.WriteLine(" Creating parameters for watcher..."); 31 | 32 | foreach (var parameter in tuple.Item2) 33 | { 34 | parameter.WatcherId = watcher.Id; 35 | parameter.Active = true; 36 | parameter.CreationUser = audit.CreationUser; 37 | parameter.CreationDateTime = DateTime.Now; 38 | 39 | ctx.WatcherParameter.Add(parameter); 40 | 41 | ctx.SaveChanges(); 42 | } 43 | 44 | Console.WriteLine(" The watcher parameters were created successfully"); 45 | } 46 | 47 | Console.WriteLine(" The watchers were created successfully"); 48 | Console.WriteLine(); 49 | 50 | Console.WriteLine("Creating resource categories..."); 51 | 52 | foreach (var item in ResourceCategories.Items) 53 | { 54 | item.Active = true; 55 | item.CreationUser = audit.CreationUser; 56 | item.CreationDateTime = DateTime.Now; 57 | 58 | ctx.ResourceCategory.Add(item); 59 | 60 | Console.WriteLine($" Adding '{item.Name}' resource category..."); 61 | 62 | ctx.SaveChanges(); 63 | } 64 | 65 | Console.WriteLine(" The resource categories were created successfully"); 66 | Console.WriteLine(); 67 | 68 | Console.WriteLine("Creating resources..."); 69 | 70 | foreach (var item in Resources.Items) 71 | { 72 | item.Active = true; 73 | item.CreationUser = audit.CreationUser; 74 | item.CreationDateTime = DateTime.Now; 75 | 76 | ctx.Resource.Add(item); 77 | 78 | Console.WriteLine($" Adding '{item.Name}' resource..."); 79 | 80 | ctx.SaveChanges(); 81 | } 82 | 83 | Console.WriteLine(" The watchers were created successfully"); 84 | Console.WriteLine(); 85 | 86 | Console.WriteLine("Creating environments..."); 87 | 88 | foreach (var item in Environments.Items) 89 | { 90 | item.Active = true; 91 | item.CreationUser = audit.CreationUser; 92 | item.CreationDateTime = DateTime.Now; 93 | 94 | ctx.Environment.Add(item); 95 | 96 | Console.WriteLine($" Adding '{item.Name}' environment..."); 97 | 98 | ctx.SaveChanges(); 99 | } 100 | 101 | Console.WriteLine(" The environments were created successfully"); 102 | Console.WriteLine(); 103 | 104 | Console.WriteLine("Creating resource watches..."); 105 | 106 | foreach (var tuple in ResourceWatches.Items) 107 | { 108 | var resourceWatch = tuple.Item1; 109 | 110 | resourceWatch.Active = true; 111 | resourceWatch.CreationUser = audit.CreationUser; 112 | resourceWatch.CreationDateTime = DateTime.Now; 113 | 114 | ctx.ResourceWatch.Add(resourceWatch); 115 | 116 | Console.WriteLine($" Adding '{resourceWatch.ResourceId}' resource watch..."); 117 | 118 | ctx.SaveChanges(); 119 | 120 | Console.WriteLine("Creating resource watches parameters..."); 121 | 122 | foreach (var resourceWatchParameter in tuple.Item2) 123 | { 124 | resourceWatchParameter.ResourceWatchId = resourceWatch.Id; 125 | resourceWatchParameter.Active = true; 126 | resourceWatchParameter.CreationUser = audit.CreationUser; 127 | resourceWatchParameter.CreationDateTime = DateTime.Now; 128 | 129 | ctx.ResourceWatchParameter.Add(resourceWatchParameter); 130 | 131 | ctx.SaveChanges(); 132 | } 133 | 134 | Console.WriteLine(" The resource watches parameters were created successfully"); 135 | } 136 | 137 | Console.WriteLine("The resource watches were created successfully"); 138 | Console.WriteLine(); 139 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Seeds/Environment.cs: -------------------------------------------------------------------------------- 1 | using Env = TheWatcher.Domain.Core.Models.Environment; 2 | 3 | namespace TheWatcher.Seed.Db.Seeds 4 | { 5 | internal class Environments 6 | { 7 | public static IEnumerable Items 8 | { 9 | get 10 | { 11 | yield return new Env { Name = "Development" }; 12 | 13 | yield return new Env { Name = "QA" }; 14 | 15 | yield return new Env { Name = "Staging" }; 16 | 17 | yield return new Env { Name = "Production" }; 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Seeds/ResourceCategories.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.Seed.Db.Seeds 4 | { 5 | internal class ResourceCategories 6 | { 7 | public static IEnumerable Items 8 | { 9 | get 10 | { 11 | yield return new ResourceCategory 12 | { 13 | Name = "Server", 14 | WatcherId = 1 15 | }; 16 | 17 | yield return new ResourceCategory 18 | { 19 | Name = "RESTful API", 20 | WatcherId = 2 21 | }; 22 | 23 | yield return new ResourceCategory 24 | { 25 | Name = "SQL Server Database", 26 | WatcherId = 3 27 | }; 28 | 29 | yield return new ResourceCategory 30 | { 31 | Name = "PostgreSQL Database", 32 | WatcherId = 4 33 | }; 34 | 35 | yield return new ResourceCategory 36 | { 37 | Name = "MongoDB Database", 38 | WatcherId = 5 39 | }; 40 | 41 | yield return new ResourceCategory 42 | { 43 | Name = "Broker", 44 | WatcherId = 6 45 | }; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Seeds/ResourceWatches.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.Seed.Db.Seeds 4 | { 5 | internal class ResourceWatches 6 | { 7 | public static IEnumerable<(ResourceWatch, List)> Items 8 | { 9 | get 10 | { 11 | // Ping 12 | 13 | yield return (new ResourceWatch 14 | { 15 | ResourceId = 1, 16 | EnvironmentId = 1, 17 | Interval = 10000, 18 | WatchCount = 0 19 | }, new List 20 | { 21 | new() 22 | { 23 | ResourceWatchId = 1, 24 | Parameter = "IPAddress", 25 | Value = " 192.168.1.1" 26 | } 27 | }); 28 | 29 | // RESTful API 30 | 31 | yield return (new ResourceWatch 32 | { 33 | ResourceId = 2, 34 | EnvironmentId = 1, 35 | Interval = 10000, 36 | WatchCount = 0 37 | }, new List 38 | { 39 | new() 40 | { 41 | ResourceWatchId = 2, 42 | Parameter = "Endpoint", 43 | Value = "https://api.ipify.org?format=json" 44 | } 45 | }); 46 | 47 | // SQL Server 48 | 49 | yield return (new ResourceWatch 50 | { 51 | ResourceId = 3, 52 | EnvironmentId = 1, 53 | Interval = 15000, 54 | WatchCount = 0 55 | }, new List 56 | { 57 | new() 58 | { 59 | ResourceWatchId = 3, 60 | Parameter = "ConnectionString", 61 | Value = "Server=(local); Database=TheWatcher; Integrated Security=yes; TrustServerCertificate=true;" 62 | } 63 | }); 64 | 65 | // Mongo DB 66 | 67 | yield return (new ResourceWatch 68 | { 69 | ResourceId = 4, 70 | EnvironmentId = 1, 71 | Interval = 20000, 72 | WatchCount = 0 73 | }, new List 74 | { 75 | new() 76 | { 77 | ResourceWatchId = 4, 78 | Parameter = "ConnectionString", 79 | Value = "mongodb://localhost:27017" 80 | }, 81 | new() 82 | { 83 | ResourceWatchId = 4, 84 | Parameter = "DatabaseName", 85 | Value = "TheWatcher" 86 | } 87 | }); 88 | 89 | // RabbitMQ 90 | 91 | yield return (new ResourceWatch 92 | { 93 | ResourceId = 5, 94 | EnvironmentId = 1, 95 | Interval = 30000, 96 | WatchCount = 0 97 | }, new List 98 | { 99 | new() 100 | { 101 | ResourceWatchId = 5, 102 | Parameter = "HostName", 103 | Value = "localhost" 104 | } 105 | }); 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Seeds/Resources.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.Seed.Db.Seeds 4 | { 5 | internal class Resources 6 | { 7 | public static IEnumerable Items 8 | { 9 | get 10 | { 11 | yield return new Resource 12 | { 13 | Name = "Watcher Sample for Default gateway", 14 | ResourceCategoryId = 1 15 | }; 16 | 17 | yield return new Resource 18 | { 19 | Name = "Watcher Sample for RESTful API", 20 | ResourceCategoryId = 2 21 | }; 22 | 23 | yield return new Resource 24 | { 25 | Name = "SQL Server Database Watcher Sample", 26 | ResourceCategoryId = 3 27 | }; 28 | 29 | yield return new Resource 30 | { 31 | Name = "Mongo DB Watcher Sample", 32 | ResourceCategoryId = 5 33 | }; 34 | 35 | yield return new Resource 36 | { 37 | Name = "Rabbit MQ Watcher Sample", 38 | ResourceCategoryId = 6 39 | }; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/Seeds/Watchers.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | using TheWatcher.Watchers.MongoDB; 3 | using TheWatcher.Watchers.PingWatcher; 4 | using TheWatcher.Watchers.PostgreSQL; 5 | using TheWatcher.Watchers.RabbitMQ; 6 | using TheWatcher.Watchers.RESTfulGet; 7 | using TheWatcher.Watchers.SqlServer; 8 | 9 | namespace TheWatcher.Seed.Db.Seeds 10 | { 11 | internal class Watchers 12 | { 13 | public static IEnumerable<(Watcher, List)> Items 14 | { 15 | get 16 | { 17 | yield return (new Watcher 18 | { 19 | Name = "Ping watcher", 20 | Description = "Watcher for Ping requests", 21 | ClassName = typeof(PingWatcher).FullName, 22 | ClassGuid = new PingWatcher().Guid, 23 | AssemblyQualifiedName = typeof(PingWatcher).AssemblyQualifiedName 24 | }, new List 25 | { 26 | new WatcherParameter 27 | { 28 | Parameter = "IPAddress", 29 | Value = "", 30 | IsDefault = false 31 | } 32 | }); 33 | 34 | yield return (new Watcher 35 | { 36 | Name = "RESTfulGet watcher", 37 | Description = "Watcher for RESTful API", 38 | ClassName = typeof(RESTfulGetWatcher).FullName, 39 | ClassGuid = new RESTfulGetWatcher().Guid, 40 | AssemblyQualifiedName = typeof(RESTfulGetWatcher).AssemblyQualifiedName 41 | }, new List 42 | { 43 | new WatcherParameter 44 | { 45 | Parameter = "Endpoint", 46 | Value = "", 47 | IsDefault = false 48 | } 49 | }); 50 | 51 | yield return (new Watcher 52 | { 53 | Name = "SQL Server watcher", 54 | Description = "Watcher for SQL Server databases", 55 | ClassName = typeof(SqlServerDatabaseWatcher).FullName, 56 | ClassGuid = new SqlServerDatabaseWatcher().Guid, 57 | AssemblyQualifiedName = typeof(SqlServerDatabaseWatcher).AssemblyQualifiedName 58 | }, new List 59 | { 60 | new WatcherParameter 61 | { 62 | Parameter = "ConnectionString", 63 | Value = "", 64 | IsDefault = false 65 | } 66 | }); 67 | 68 | yield return (new Watcher 69 | { 70 | Name = "PostgreSQL watcher", 71 | Description = "Watcher for PostgreSQL databases", 72 | ClassName = typeof(PostgreSQLDatabaseWatcher).FullName, 73 | ClassGuid = new PostgreSQLDatabaseWatcher().Guid, 74 | AssemblyQualifiedName = typeof(PostgreSQLDatabaseWatcher).AssemblyQualifiedName 75 | }, new List 76 | { 77 | new WatcherParameter 78 | { 79 | Parameter = "ConnectionString", 80 | Value = "", 81 | IsDefault = false 82 | } 83 | }); 84 | 85 | yield return (new Watcher 86 | { 87 | Name = "Mongo DB watcher", 88 | Description = "Watcher for Mongo DB", 89 | ClassName = typeof(MongoDBWatcher).FullName, 90 | ClassGuid = new MongoDBWatcher().Guid, 91 | AssemblyQualifiedName = typeof(MongoDBWatcher).AssemblyQualifiedName 92 | }, new List 93 | { 94 | new WatcherParameter 95 | { 96 | Parameter = "DatabaseName", 97 | Value = "", 98 | IsDefault = false 99 | } 100 | }); 101 | 102 | yield return (new Watcher 103 | { 104 | Name = "Rabbit MQ watcher", 105 | Description = "Watcher for Rabbit MQ", 106 | ClassName = typeof(RabbitMQWatcher).FullName, 107 | ClassGuid = new RabbitMQWatcher().Guid, 108 | AssemblyQualifiedName = typeof(RabbitMQWatcher).AssemblyQualifiedName 109 | }, new List 110 | { 111 | new WatcherParameter 112 | { 113 | Parameter = "HostName", 114 | Value = "", 115 | IsDefault = false 116 | } 117 | }); 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Seed/TheWatcher.Seed.Db/TheWatcher.Seed.Db.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | enable 7 | disable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/CorsSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Cors.Infrastructure; 2 | 3 | namespace TheWatcher.API.Common 4 | { 5 | public class CorsSettings 6 | { 7 | public List Policies { get; set; } 8 | } 9 | 10 | public class CorsPolicySetting 11 | { 12 | public string? Name { get; set; } 13 | public CorsPolicy Policy { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/Contracts/IListResponse.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Common.Models.Contracts 2 | { 3 | public interface IListResponse : IResponse 4 | { 5 | IEnumerable Model { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/Contracts/IResponse.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Common.Models.Contracts 2 | { 3 | public interface IResponse 4 | { 5 | string Message { get; set; } 6 | bool Failed { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/Contracts/ISingleResponse.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Common.Models.Contracts 2 | { 3 | public interface ISingleResponse 4 | { 5 | TModel Model { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Microsoft.AspNetCore.Mvc; 3 | using TheWatcher.API.Common.Models.Contracts; 4 | 5 | namespace TheWatcher.API.Common.Models 6 | { 7 | public static class Extensions 8 | { 9 | public static OkObjectResult ToOkResult(this IResponse response) 10 | => new (response) 11 | { 12 | StatusCode = (int)HttpStatusCode.OK 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/ListResponse.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.API.Common.Models.Contracts; 2 | 3 | namespace TheWatcher.API.Common.Models 4 | { 5 | public record ListResponse : Response, IListResponse 6 | { 7 | public ListResponse() 8 | { 9 | } 10 | 11 | public ListResponse(IEnumerable model) 12 | { 13 | Model = model; 14 | } 15 | 16 | public IEnumerable Model { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/Response.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.API.Common.Models.Contracts; 2 | 3 | namespace TheWatcher.API.Common.Models 4 | { 5 | public record Response : IResponse 6 | { 7 | public string Message { get; set; } 8 | public bool Failed { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Models/SingleResponse.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.API.Common.Models.Contracts; 2 | 3 | namespace TheWatcher.API.Common.Models 4 | { 5 | public record SingleResponse : Response, ISingleResponse 6 | { 7 | public SingleResponse() 8 | { 9 | } 10 | 11 | public SingleResponse(TModel model) 12 | { 13 | Model = model; 14 | } 15 | 16 | public TModel Model { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | 3 | // Add services to the container. 4 | 5 | builder.Services.AddControllers(); 6 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 7 | builder.Services.AddEndpointsApiExplorer(); 8 | builder.Services.AddSwaggerGen(); 9 | 10 | var app = builder.Build(); 11 | 12 | // Configure the HTTP request pipeline. 13 | if (app.Environment.IsDevelopment()) 14 | { 15 | app.UseSwagger(); 16 | app.UseSwaggerUI(); 17 | } 18 | 19 | app.UseHttpsRedirection(); 20 | 21 | app.UseAuthorization(); 22 | 23 | app.MapControllers(); 24 | 25 | app.Run(); 26 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "TheWatcher.API.Common": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "https://localhost:13001;", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/TheWatcher.API.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | disable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Common/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Controllers/MonitorController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.EntityFrameworkCore; 3 | using TheWatcher.API.Common.Models; 4 | using TheWatcher.API.Common.Models.Contracts; 5 | using TheWatcher.Domain.Core; 6 | using TheWatcher.Domain.Core.QueryModels; 7 | 8 | namespace TheWatcher.API.Monitor.Controllers 9 | { 10 | [ApiController] 11 | [Route("api/v1")] 12 | public class MonitorController : ControllerBase 13 | { 14 | private readonly ILogger _logger; 15 | private readonly TheWatcherDbContext _dbContext; 16 | 17 | public MonitorController(ILogger logger, TheWatcherDbContext dbContext) 18 | { 19 | _logger = logger; 20 | _dbContext = dbContext; 21 | } 22 | 23 | [HttpGet("monitor")] 24 | [ProducesResponseType(200, Type = typeof(IListResponse))] 25 | [ProducesResponseType(500)] 26 | public async Task GetMonitorAsync() 27 | { 28 | var model = await _dbContext.GetResourceWatchItems().ToListAsync(); 29 | 30 | var response = new ListResponse(model); 31 | 32 | return response.ToOkResult(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/HubMethods.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Monitor 2 | { 3 | public static class HubMethods 4 | { 5 | public const string ReceiveResourceWatch = "receiveResourceWatch"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Hubs/Models/ResourceWatchArg.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Monitor.Hubs.Models 2 | { 3 | public record ResourceWatchArg 4 | { 5 | public short? ResourceId { get; set; } 6 | public string Resource { get; set; } 7 | public short? EnvironmentId { get; set; } 8 | public string Environment { get; set; } 9 | public bool IsSuccess { get; set; } 10 | public DateTime LastWatch { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Hubs/MonitorHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | 3 | namespace TheWatcher.API.Monitor.Hubs 4 | { 5 | public class MonitorHub : Hub 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Serilog; 3 | using Serilog.Events; 4 | using TheWatcher.API.Common; 5 | using TheWatcher.API.Monitor.Hubs; 6 | using TheWatcher.API.Monitor.Services; 7 | using TheWatcher.Domain.Core; 8 | 9 | var builder = WebApplication.CreateBuilder(args); 10 | 11 | // Add services to the container. 12 | builder.Services.AddControllers(); 13 | 14 | builder.Services.AddHostedService(); 15 | 16 | builder.Host.UseSerilog(); 17 | 18 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 19 | builder.Services.AddEndpointsApiExplorer(); 20 | builder.Services.AddSwaggerGen(); 21 | 22 | builder 23 | .Services 24 | .AddDbContext(options => options.UseSqlServer(builder.Configuration.GetConnectionString("TheWatcher")), ServiceLifetime.Transient) 25 | ; 26 | 27 | var corsSettings = new CorsSettings(); 28 | 29 | builder.Configuration.Bind("CorsSettings", corsSettings); 30 | 31 | foreach (var item in corsSettings.Policies) 32 | { 33 | builder.Services.AddCors(options => options.AddPolicy(item.Name, builder => 34 | { 35 | builder 36 | .AllowCredentials() 37 | .AllowAnyHeader() 38 | .AllowAnyMethod() 39 | .WithOrigins(item.Policy.Origins.ToList().ToArray()) 40 | ; 41 | })); 42 | } 43 | 44 | builder 45 | .Services 46 | .AddSignalR(options => options.EnableDetailedErrors = true) 47 | ; 48 | 49 | var app = builder.Build(); 50 | 51 | // Configure the HTTP request pipeline. 52 | if (app.Environment.IsDevelopment()) 53 | { 54 | app.UseSwagger(); 55 | app.UseSwaggerUI(); 56 | } 57 | 58 | foreach (var item in corsSettings.Policies) 59 | { 60 | app.UseCors(item.Name); 61 | } 62 | 63 | app.UseHttpsRedirection(); 64 | 65 | app.UseAuthorization(); 66 | 67 | app.MapControllers(); 68 | app.MapHub("/monitorhub"); 69 | 70 | Log.Logger = new LoggerConfiguration() 71 | .MinimumLevel.Override("Microsoft", LogEventLevel.Information) 72 | .Enrich.FromLogContext() 73 | .WriteTo.Console() 74 | .WriteTo.File("TheWatcher.API.Monitor.log") 75 | .CreateLogger() 76 | ; 77 | 78 | try 79 | { 80 | Log.Information("Starting web host"); 81 | app.Run(); 82 | return 1; 83 | } 84 | catch (Exception ex) 85 | { 86 | Log.Fatal(ex, "Host terminated unexpectedly"); 87 | return 0; 88 | } 89 | finally 90 | { 91 | Log.CloseAndFlush(); 92 | } 93 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "TheWatcher.API.Monitor": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "https://localhost:13002;", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Services/Models/ResourceWatchItemModel.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.QueryModels; 2 | using TheWatcher.Library.Core; 3 | 4 | namespace TheWatcher.API.Monitor.Services.Models 5 | { 6 | public class ResourceWatchItemModel : ResourceWatchQueryModel 7 | { 8 | public ResourceWatchItemModel() 9 | { 10 | Param = new(); 11 | } 12 | 13 | public WatcherParam Param { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/Services/MonitorService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | using Microsoft.EntityFrameworkCore; 3 | using TheWatcher.API.Monitor.Hubs; 4 | using TheWatcher.API.Monitor.Hubs.Models; 5 | using TheWatcher.API.Monitor.Services.Models; 6 | using TheWatcher.Domain.Core; 7 | using TheWatcher.Library.Core.Contracts; 8 | 9 | namespace TheWatcher.API.Monitor.Services 10 | { 11 | public class MonitorService : IHostedService, IDisposable 12 | { 13 | private readonly ILogger _logger; 14 | private readonly IServiceScopeFactory _serviceScopeFactory; 15 | private readonly IServiceScope _serviceScope; 16 | private readonly List _timers; 17 | 18 | public MonitorService(ILogger logger, IServiceScopeFactory serviceScopeFactory) 19 | { 20 | _logger = logger; 21 | _serviceScopeFactory = serviceScopeFactory; 22 | _serviceScope = _serviceScopeFactory.CreateScope(); 23 | _timers = new(); 24 | } 25 | 26 | private IHubContext _hubContext; 27 | 28 | public async Task StartAsync(CancellationToken stoppingToken) 29 | { 30 | _logger.LogDebug("Starting watchers..."); 31 | 32 | _hubContext = _serviceScope.ServiceProvider.GetService>(); 33 | 34 | var dbContext = _serviceScope.ServiceProvider.GetService(); 35 | var list = await dbContext.GetResourceWatchItems().ToListAsync(stoppingToken); 36 | 37 | var model = list 38 | .Select(item => new ResourceWatchItemModel 39 | { 40 | Id = item.Id, 41 | ResourceId = item.ResourceId, 42 | Resource = item.Resource, 43 | ResourceCategory = item.ResourceCategory, 44 | AssemblyQualifiedName = item.AssemblyQualifiedName, 45 | Environment = item.Environment, 46 | EnvironmentId = item.EnvironmentId, 47 | Interval = item.Interval 48 | }) 49 | .ToList() 50 | ; 51 | 52 | foreach (var resourceWatchItem in model) 53 | { 54 | var parameters = await dbContext 55 | .ResourceWatchParameter 56 | .Where(item => item.ResourceWatchId == resourceWatchItem.Id) 57 | .ToListAsync() 58 | ; 59 | 60 | foreach (var param in parameters) 61 | { 62 | resourceWatchItem.Param.Values.Add(param.Parameter, param.Value); 63 | } 64 | 65 | _timers.Add(new Timer(Monitoring, resourceWatchItem, TimeSpan.Zero, TimeSpan.FromMilliseconds((double)resourceWatchItem.Interval))); 66 | } 67 | 68 | await Task.CompletedTask; 69 | } 70 | 71 | public async Task StopAsync(CancellationToken stoppingToken) 72 | { 73 | _logger.LogDebug("Stopping watchers..."); 74 | 75 | foreach (var item in _timers) 76 | { 77 | item.Change(Timeout.Infinite, 0); 78 | } 79 | 80 | await Task.CompletedTask; 81 | } 82 | 83 | public void Dispose() 84 | { 85 | foreach (var item in _timers) 86 | { 87 | item.Dispose(); 88 | } 89 | } 90 | 91 | public async void Monitoring(object state) 92 | { 93 | if (state is ResourceWatchItemModel cast) 94 | { 95 | _logger.LogInformation($"Watcher for '{cast.Resource}' resource is executing in '{cast.Environment}' environment, interval: '{cast.Interval}'..."); 96 | 97 | var watcherType = Type.GetType(cast.AssemblyQualifiedName, true); 98 | 99 | var watcherInstance = (IWatcher)Activator.CreateInstance(watcherType); 100 | 101 | var result = await watcherInstance.WatchAsync(cast.Param); 102 | 103 | if (result.IsSuccess) 104 | _logger.LogInformation($"The watch for '{cast.Resource}' was 'Successfully' in '{cast.Environment}'"); 105 | else 106 | _logger.LogError($"The watch for '{cast.Resource}' was 'Failed' in '{cast.Environment}'"); 107 | 108 | await _hubContext.Clients.All.SendAsync(HubMethods.ReceiveResourceWatch, new ResourceWatchArg 109 | { 110 | Resource = cast.Resource, 111 | ResourceId = cast.ResourceId, 112 | Environment = cast.Environment, 113 | EnvironmentId = cast.EnvironmentId, 114 | IsSuccess = result.IsSuccess, 115 | LastWatch = result.LastWatch 116 | }); 117 | 118 | var dbContext = _serviceScope.ServiceProvider.GetService(); 119 | 120 | var resourceWatch = await dbContext.GetResourceWatchAsync(cast.Id); 121 | 122 | resourceWatch.Successful = result.IsSuccess; 123 | resourceWatch.LastWatch = result.LastWatch; 124 | resourceWatch.WatchCount += 1; 125 | resourceWatch.LastUpdateDateTime = DateTime.Now; 126 | resourceWatch.LastUpdateUser = typeof(MonitorService).Name; 127 | 128 | var affectedRows = await dbContext.SaveChangesAsync(); 129 | 130 | if (affectedRows > 0) 131 | _logger.LogInformation($"Resource watch was updated for '{cast.Resource}' resource in '{cast.Environment}' environment"); 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/TheWatcher.API.Monitor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | disable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Monitor/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "CorsSettings": { 10 | "Policies": [ 11 | { 12 | "Name": "GUI", 13 | "Policy": { 14 | "Origins": [ "https://localhost:13010" ] 15 | } 16 | } 17 | ] 18 | }, 19 | "ConnectionStrings": { 20 | "TheWatcher": "Server=(local); Database=TheWatcher; Integrated Security=yes; TrustServerCertificate=true;" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Controllers/PanelController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.EntityFrameworkCore; 3 | using TheWatcher.API.Common.Models; 4 | using TheWatcher.API.Common.Models.Contracts; 5 | using TheWatcher.API.Panel.Models; 6 | using TheWatcher.Domain.Core; 7 | using TheWatcher.Domain.Core.QueryModels; 8 | 9 | namespace TheWatcher.API.Panel.Controllers 10 | { 11 | [ApiController] 12 | [Route("api/v1")] 13 | public class PanelController : ControllerBase 14 | { 15 | private readonly ILogger _logger; 16 | private readonly TheWatcherDbContext _dbContext; 17 | 18 | public PanelController(ILogger logger, TheWatcherDbContext dbContext) 19 | { 20 | _logger = logger; 21 | _dbContext = dbContext; 22 | } 23 | 24 | [HttpGet("watcher")] 25 | [ProducesResponseType(200, Type = typeof(IListResponse))] 26 | [ProducesResponseType(500)] 27 | public async Task GetWatchersAsync() 28 | { 29 | var model = await _dbContext.GetWatchers().OrderBy(item => item.Name).ToListAsync(); 30 | 31 | var response = new ListResponse(model); 32 | 33 | return response.ToOkResult(); 34 | } 35 | 36 | [HttpGet("watcher/{id}")] 37 | [ProducesResponseType(200, Type = typeof(ISingleResponse))] 38 | [ProducesResponseType(404)] 39 | [ProducesResponseType(500)] 40 | public async Task GetWatcherAsync(short? id) 41 | { 42 | var entity = await _dbContext.GetWatcherAsync(id); 43 | 44 | if (entity == null) 45 | return NotFound(); 46 | 47 | var response = new SingleResponse(new(entity)); 48 | 49 | return response.ToOkResult(); 50 | } 51 | 52 | [HttpGet("resource")] 53 | [ProducesResponseType(200, Type = typeof(IListResponse))] 54 | [ProducesResponseType(500)] 55 | public async Task GetResourcesAsync() 56 | { 57 | var model = await _dbContext.GetResources().ToListAsync(); 58 | 59 | var response = new ListResponse(model); 60 | 61 | return response.ToOkResult(); 62 | } 63 | 64 | [HttpGet("resource/{id}")] 65 | [ProducesResponseType(200, Type = typeof(ISingleResponse))] 66 | [ProducesResponseType(404)] 67 | [ProducesResponseType(500)] 68 | public async Task GetResourceAsync(short? id) 69 | { 70 | var entity = await _dbContext.GetResourceAsync(id); 71 | 72 | if (entity == null) 73 | return NotFound(); 74 | 75 | var response = new SingleResponse(new(entity)); 76 | 77 | return response.ToOkResult(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Models/ResourceDetailsModel.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.API.Panel.Models 4 | { 5 | public record ResourceDetailsModel 6 | { 7 | public ResourceDetailsModel() 8 | { 9 | } 10 | 11 | public ResourceDetailsModel(Resource entity) 12 | { 13 | Id = entity.Id; 14 | Name = entity.Name; 15 | ResourceCategoryId = entity.ResourceCategoryId; 16 | ResourceCategory = entity.ResourceCategoryFk.Name; 17 | WatcherId = entity.ResourceCategoryFk.WatcherId; 18 | Watcher = entity.ResourceCategoryFk.WatcherFk.Name; 19 | Watches = entity.ResourceWatchList.Select(item => new ResourceWatchDetailsModel(item)).ToList(); 20 | } 21 | 22 | public short? Id { get; set; } 23 | public string Name { get; set; } 24 | public short? ResourceCategoryId { get; set; } 25 | public string ResourceCategory { get; set; } 26 | public short? WatcherId { get; set; } 27 | public string Watcher { get; set; } 28 | 29 | public List Watches { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Models/ResourceWatchDetailsModel.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.API.Panel.Models 4 | { 5 | public record ResourceWatchDetailsModel 6 | { 7 | public ResourceWatchDetailsModel() 8 | { 9 | } 10 | 11 | public ResourceWatchDetailsModel(ResourceWatch entity) 12 | { 13 | Id = entity.Id; 14 | EnvironmentId = entity.EnvironmentId; 15 | Environment = entity.EnvironmentFk.Name; 16 | Successful = entity.Successful; 17 | WatchCount = entity.WatchCount; 18 | LastWatch = entity.LastWatch; 19 | Interval = entity.Interval; 20 | Parameters = entity.ResourceWatchParameterList.Select(parameter => new ResourceWatchParameterDetailsModel(parameter)).ToList(); 21 | } 22 | 23 | public short? Id { get; set; } 24 | public short? EnvironmentId { get; set; } 25 | public string Environment { get; set; } 26 | public bool? Successful { get; set; } 27 | public int? WatchCount { get; set; } 28 | public DateTime? LastWatch { get; set; } 29 | public int? Interval { get; set; } 30 | 31 | public List Parameters { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Models/ResourceWatchParameterDetailsModel.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.API.Panel.Models 4 | { 5 | public record ResourceWatchParameterDetailsModel 6 | { 7 | public ResourceWatchParameterDetailsModel() 8 | { 9 | } 10 | 11 | public ResourceWatchParameterDetailsModel(ResourceWatchParameter entity) 12 | { 13 | Parameter = entity.Parameter; 14 | Value = entity.Value; 15 | Description = entity.Description; 16 | } 17 | 18 | public string Parameter { get; set; } 19 | public string Value { get; set; } 20 | public string Description { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Models/WatcherDetailsModel.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Models; 2 | 3 | namespace TheWatcher.API.Panel.Models 4 | { 5 | public record WatcherDetailsModel 6 | { 7 | public WatcherDetailsModel() 8 | { 9 | } 10 | 11 | public WatcherDetailsModel(Watcher entity) 12 | { 13 | Id = entity.Id; 14 | Name = entity.Name; 15 | Description = entity.Description; 16 | ClassName = entity.ClassName; 17 | ClassGuid = entity.ClassGuid; 18 | AssemblyQualifiedName = entity.AssemblyQualifiedName; 19 | Parameters = entity 20 | .WatcherParameterList 21 | .Select(item => new WatcherParameterDetailsModel(item.Id, item.IsDefault, item.Parameter, item.Value, item.Description)) 22 | .ToList() 23 | ; 24 | } 25 | 26 | public short? Id { get; set; } 27 | public string Name { get; set; } 28 | public string Description { get; set; } 29 | public string ClassName { get; set; } 30 | public Guid? ClassGuid { get; set; } 31 | public string AssemblyQualifiedName { get; set; } 32 | 33 | public List Parameters { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Models/WatcherParameterDetailsModel.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.API.Panel.Models 2 | { 3 | public record WatcherParameterDetailsModel 4 | { 5 | public WatcherParameterDetailsModel() 6 | { 7 | } 8 | 9 | public WatcherParameterDetailsModel(short? id, bool? isDefault, string parameter, string value, string description) 10 | { 11 | Id = id; 12 | IsDefault = isDefault; 13 | Parameter = parameter; 14 | Value = value; 15 | Description = description; 16 | } 17 | 18 | public short? Id { get; set; } 19 | public bool? IsDefault { get; set; } 20 | public string Parameter { get; set; } 21 | public string Value { get; set; } 22 | public string Description { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Serilog; 3 | using Serilog.Events; 4 | using TheWatcher.API.Common; 5 | using TheWatcher.Domain.Core; 6 | 7 | var builder = WebApplication.CreateBuilder(args); 8 | 9 | builder.Host.UseSerilog(); 10 | 11 | // Add services to the container. 12 | builder.Services.AddControllers(); 13 | 14 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 15 | builder.Services.AddEndpointsApiExplorer(); 16 | builder.Services.AddSwaggerGen(); 17 | 18 | builder 19 | .Services 20 | .AddDbContext(options => options.UseSqlServer(builder.Configuration.GetConnectionString("TheWatcher"))) 21 | ; 22 | 23 | var corsSettings = new CorsSettings(); 24 | 25 | builder.Configuration.Bind("CorsSettings", corsSettings); 26 | 27 | foreach (var item in corsSettings.Policies) 28 | { 29 | builder.Services.AddCors(options => options.AddPolicy(item.Name, builder => 30 | { 31 | builder 32 | .AllowCredentials() 33 | .AllowAnyHeader() 34 | .AllowAnyMethod() 35 | .WithOrigins(item.Policy.Origins.ToList().ToArray()) 36 | ; 37 | })); 38 | } 39 | 40 | var app = builder.Build(); 41 | 42 | // Configure the HTTP request pipeline. 43 | if (app.Environment.IsDevelopment()) 44 | { 45 | app.UseSwagger(); 46 | app.UseSwaggerUI(); 47 | } 48 | 49 | foreach (var item in corsSettings.Policies) 50 | { 51 | app.UseCors(item.Name); 52 | } 53 | 54 | app.UseHttpsRedirection(); 55 | 56 | app.UseAuthorization(); 57 | 58 | app.MapControllers(); 59 | 60 | Log.Logger = new LoggerConfiguration() 61 | .MinimumLevel.Override("Microsoft", LogEventLevel.Information) 62 | .Enrich.FromLogContext() 63 | .WriteTo.Console() 64 | .WriteTo.File("TheWatcher.API.Panel.log") 65 | .CreateLogger() 66 | ; 67 | 68 | try 69 | { 70 | Log.Information("Starting web host"); 71 | app.Run(); 72 | return 1; 73 | } 74 | catch (Exception ex) 75 | { 76 | Log.Fatal(ex, "Host terminated unexpectedly"); 77 | return 0; 78 | } 79 | finally 80 | { 81 | Log.CloseAndFlush(); 82 | } 83 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "TheWatcher.API.Panel": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "https://localhost:13003;", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/TheWatcher.API.Panel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | disable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.API.Panel/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "CorsSettings": { 10 | "Policies": [ 11 | { 12 | "Name": "GUI", 13 | "Policy": { 14 | "Origins": [ "https://localhost:13010" ] 15 | } 16 | } 17 | ] 18 | }, 19 | "ConnectionStrings": { 20 | "TheWatcher": "Server=(local); Database=TheWatcher; Integrated Security=yes; TrustServerCertificate=true;" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Common/Entity.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Domain.Core.Common 2 | { 3 | public abstract class Entity : IEntity 4 | { 5 | public bool? Active { get; set; } 6 | public string CreationUser { get; set; } 7 | public DateTime? CreationDateTime { get; set; } 8 | public string LastUpdateUser { get; set; } 9 | public DateTime? LastUpdateDateTime { get; set; } 10 | public byte[] Version { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Common/IEntity.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Domain.Core.Common 2 | { 3 | public interface IEntity 4 | { 5 | bool? Active { get; set; } 6 | string CreationUser { get; set; } 7 | DateTime? CreationDateTime { get; set; } 8 | string LastUpdateUser { get; set; } 9 | DateTime? LastUpdateDateTime { get; set; } 10 | byte[] Version { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/Common/EntityConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Common; 4 | 5 | namespace TheWatcher.Domain.Core.Configurations.Common 6 | { 7 | internal class EntityConfiguration : IEntityTypeConfiguration where TEntity : Entity 8 | { 9 | public virtual void Configure(EntityTypeBuilder builder) 10 | { 11 | builder 12 | .Property(p => p.Active) 13 | .HasColumnType("bit") 14 | .IsRequired() 15 | ; 16 | 17 | builder 18 | .Property(p => p.CreationUser) 19 | .HasColumnType("nvarchar") 20 | .HasMaxLength(50) 21 | .IsRequired() 22 | ; 23 | 24 | builder 25 | .Property(p => p.CreationDateTime) 26 | .HasColumnType("datetime") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.LastUpdateUser) 32 | .HasColumnType("nvarchar") 33 | .HasMaxLength(50) 34 | ; 35 | 36 | builder 37 | .Property(p => p.LastUpdateDateTime) 38 | .HasColumnType("datetime") 39 | ; 40 | 41 | builder 42 | .Property(p => p.Version) 43 | .HasColumnType("rowversion") 44 | ; 45 | 46 | // Add configuration for row version 47 | 48 | builder 49 | .Property(p => p.Version) 50 | .ValueGeneratedOnAddOrUpdate() 51 | .IsRowVersion() 52 | ; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/EnvironmentConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using Environment = TheWatcher.Domain.Core.Models.Environment; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class EnvironmentConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("Environment", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.Name) 32 | .HasColumnType("nvarchar") 33 | .HasMaxLength(100) 34 | .IsRequired() 35 | ; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/ResourceCategoryConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class ResourceCategoryConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("ResourceCategory", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.Name) 32 | .HasColumnType("nvarchar") 33 | .HasMaxLength(100) 34 | .IsRequired() 35 | ; 36 | 37 | builder 38 | .Property(p => p.WatcherId) 39 | .HasColumnType("smallint") 40 | ; 41 | 42 | // Add configuration for uniques 43 | 44 | builder 45 | .HasIndex(p => p.Name) 46 | .IsUnique() 47 | .HasDatabaseName("UQ_dbo_ResourceCategory_Name") 48 | ; 49 | 50 | // Add configuration for foreign keys 51 | 52 | builder 53 | .HasOne(p => p.WatcherFk) 54 | .WithMany(b => b.ResourceCategoryList) 55 | .HasForeignKey(p => p.WatcherId) 56 | .HasConstraintName("FK_dbo_ResourceCategory_WatcherId_dbo_Watcher") 57 | ; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/ResourceConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class ResourceConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("Resource", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.Name) 32 | .HasColumnType("nvarchar") 33 | .HasMaxLength(100) 34 | ; 35 | 36 | builder 37 | .Property(p => p.ResourceCategoryId) 38 | .HasColumnType("smallint") 39 | ; 40 | 41 | // Add configuration for foreign keys 42 | 43 | builder 44 | .HasOne(p => p.ResourceCategoryFk) 45 | .WithMany(b => b.ResourceList) 46 | .HasForeignKey(p => p.ResourceCategoryId) 47 | .HasConstraintName("FK_dbo_Resource_ResourceCategoryId_dbo_ResourceCategory") 48 | ; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/ResourceWatchConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class ResourceWatchConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("ResourceWatch", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.ResourceId) 32 | .HasColumnType("smallint") 33 | .IsRequired() 34 | ; 35 | 36 | builder 37 | .Property(p => p.EnvironmentId) 38 | .HasColumnType("smallint") 39 | .IsRequired() 40 | ; 41 | 42 | builder 43 | .Property(p => p.Interval) 44 | .HasColumnType("int") 45 | .IsRequired() 46 | ; 47 | 48 | builder 49 | .Property(p => p.Description) 50 | .HasColumnType("nvarchar(max)") 51 | ; 52 | 53 | // Add configuration for uniques 54 | 55 | builder 56 | .HasIndex(p => new { p.ResourceId, p.EnvironmentId }) 57 | .IsUnique() 58 | .HasDatabaseName("UQ_dbo_ResourceWatch_ResourceId_EnvironmentId") 59 | ; 60 | 61 | // Add configuration for foreign keys 62 | 63 | builder 64 | .HasOne(p => p.ResourceFk) 65 | .WithMany(b => b.ResourceWatchList) 66 | .HasForeignKey(p => p.ResourceId) 67 | .HasConstraintName("FK_dbo_ResourceWatch_ResourceId_dbo_Resource") 68 | ; 69 | 70 | builder 71 | .HasOne(p => p.EnvironmentFk) 72 | .WithMany(b => b.ResourceWatchList) 73 | .HasForeignKey(p => p.EnvironmentId) 74 | .HasConstraintName("FK_dbo_ResourceWatch_EnvironmentId_dbo_Environment") 75 | ; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/ResourceWatchLogConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class ResourceWatchLogConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("ResourceWatchLog", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.ResourceWatchId) 32 | .HasColumnType("smallint") 33 | .IsRequired() 34 | ; 35 | 36 | builder 37 | .Property(p => p.AssemblyQualifiedName) 38 | .HasColumnType("nvarchar") 39 | .HasMaxLength(511) 40 | .IsRequired() 41 | ; 42 | 43 | builder 44 | .Property(p => p.ActionName) 45 | .HasColumnType("nvarchar") 46 | .HasMaxLength(511) 47 | .IsRequired() 48 | ; 49 | 50 | builder 51 | .Property(p => p.Successful) 52 | .HasColumnType("bit") 53 | .IsRequired() 54 | ; 55 | 56 | builder 57 | .Property(p => p.Message) 58 | .HasColumnType("nvarchar(max)") 59 | .IsRequired() 60 | ; 61 | 62 | builder 63 | .Property(p => p.ErrorMessage) 64 | .HasColumnType("nvarchar(max)") 65 | ; 66 | 67 | // Add configuration for foreign keys 68 | 69 | builder 70 | .HasOne(p => p.ResourceWatchFk) 71 | .WithMany(b => b.ResourceWatchLogList) 72 | .HasForeignKey(p => p.ResourceWatchId) 73 | .HasConstraintName("FK_dbo_ResourceWatchLog_ResourceWatchId_dbo_ResourceWatch") 74 | ; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/ResourceWatchParameterConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class ResourceWatchParameterConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("ResourceWatchParameter", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.ResourceWatchId) 32 | .HasColumnType("smallint") 33 | .IsRequired() 34 | ; 35 | 36 | builder 37 | .Property(p => p.Parameter) 38 | .HasColumnType("nvarchar") 39 | .HasMaxLength(100) 40 | .IsRequired() 41 | ; 42 | 43 | builder 44 | .Property(p => p.Value) 45 | .HasColumnType("nvarchar(max)") 46 | ; 47 | 48 | builder 49 | .Property(p => p.Description) 50 | .HasColumnType("nvarchar(max)") 51 | ; 52 | 53 | // Add configuration for uniques 54 | 55 | builder 56 | .HasIndex(p => new { p.ResourceWatchId, p.Parameter }) 57 | .IsUnique() 58 | .HasDatabaseName("UQ_dbo_ResourceWatchParameter_ResourceWatchId_Parameter") 59 | ; 60 | 61 | // Add configuration for foreign keys 62 | 63 | builder 64 | .HasOne(p => p.ResourceWatchFk) 65 | .WithMany(b => b.ResourceWatchParameterList) 66 | .HasForeignKey(p => p.ResourceWatchId) 67 | .HasConstraintName("FK_dbo_ResourceWatchParameter_ResourceWatchId_dbo_ResourceWatch") 68 | ; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/WatcherConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class WatcherConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("Watcher", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.Name) 32 | .HasColumnType("nvarchar") 33 | .HasMaxLength(100) 34 | .IsRequired() 35 | ; 36 | 37 | builder 38 | .Property(p => p.Description) 39 | .HasColumnType("nvarchar(max)") 40 | ; 41 | 42 | builder 43 | .Property(p => p.ClassName) 44 | .HasColumnType("nvarchar") 45 | .HasMaxLength(511) 46 | .IsRequired() 47 | ; 48 | 49 | builder 50 | .Property(p => p.ClassGuid) 51 | .HasColumnType("uniqueidentifier") 52 | .IsRequired() 53 | ; 54 | 55 | builder 56 | .Property(p => p.AssemblyQualifiedName) 57 | .HasColumnType("nvarchar") 58 | .HasMaxLength(511) 59 | .IsRequired() 60 | ; 61 | 62 | // Add configuration for uniques 63 | 64 | builder 65 | .HasIndex(p => p.Name) 66 | .IsUnique() 67 | .HasDatabaseName("UQ_dbo_Watcher_Name") 68 | ; 69 | 70 | builder 71 | .HasIndex(p => p.ClassName) 72 | .IsUnique() 73 | .HasDatabaseName("UQ_dbo_Watcher_ClassName") 74 | ; 75 | 76 | builder 77 | .HasIndex(p => p.ClassGuid) 78 | .IsUnique() 79 | .HasDatabaseName("UQ_dbo_Watcher_ClassGuid") 80 | ; 81 | 82 | builder 83 | .HasIndex(p => p.AssemblyQualifiedName) 84 | .IsUnique() 85 | .HasDatabaseName("UQ_dbo_Watcher_AssemblyQualifiedName") 86 | ; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Configurations/WatcherParameterConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using TheWatcher.Domain.Core.Configurations.Common; 4 | using TheWatcher.Domain.Core.Models; 5 | 6 | namespace TheWatcher.Domain.Core.Configurations 7 | { 8 | internal class WatcherParameterConfiguration : EntityConfiguration 9 | { 10 | public override void Configure(EntityTypeBuilder builder) 11 | { 12 | base.Configure(builder); 13 | 14 | // Set configuration for entity 15 | builder.ToTable("WatcherParameter", "dbo"); 16 | 17 | // Set key for entity 18 | builder.HasKey(p => p.Id); 19 | 20 | // Set identity for entity (auto increment) 21 | builder.Property(p => p.Id).UseIdentityColumn(); 22 | 23 | // Set configuration for columns 24 | builder 25 | .Property(p => p.Id) 26 | .HasColumnType("smallint") 27 | .IsRequired() 28 | ; 29 | 30 | builder 31 | .Property(p => p.WatcherId) 32 | .HasColumnType("smallint") 33 | .IsRequired() 34 | ; 35 | 36 | builder 37 | .Property(p => p.Parameter) 38 | .HasColumnType("nvarchar") 39 | .HasMaxLength(100) 40 | .IsRequired() 41 | ; 42 | 43 | builder 44 | .Property(p => p.Value) 45 | .HasColumnType("nvarchar(max)") 46 | ; 47 | 48 | builder 49 | .Property(p => p.IsDefault) 50 | .HasColumnType("bit") 51 | ; 52 | 53 | builder 54 | .Property(p => p.Description) 55 | .HasColumnType("nvarchar(max)") 56 | ; 57 | 58 | // Add configuration for uniques 59 | 60 | builder 61 | .HasIndex(p => new { p.WatcherId, p.Parameter }) 62 | .IsUnique() 63 | .HasDatabaseName("UQ_dbo_WatcherParameter_WatcherId_Parameter") 64 | ; 65 | 66 | // Add configuration for foreign keys 67 | 68 | builder 69 | .HasOne(p => p.WatcherFk) 70 | .WithMany(b => b.WatcherParameterList) 71 | .HasForeignKey(p => p.WatcherId) 72 | .HasConstraintName("FK_dbo_WatcherParameter_WatcherId_dbo_Watcher") 73 | ; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/Environment.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using TheWatcher.Domain.Core.Common; 3 | 4 | namespace TheWatcher.Domain.Core.Models 5 | { 6 | public partial class Environment : Entity 7 | { 8 | public Environment() 9 | { 10 | } 11 | 12 | public Environment(short? id) 13 | { 14 | Id = id; 15 | } 16 | 17 | public short? Id { get; set; } 18 | public string Name { get; set; } 19 | 20 | public virtual Collection ResourceWatchList { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/Resource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using TheWatcher.Domain.Core.Common; 3 | 4 | namespace TheWatcher.Domain.Core.Models 5 | { 6 | public partial class Resource : Entity 7 | { 8 | public Resource() 9 | { 10 | } 11 | 12 | public Resource(short? id) 13 | { 14 | Id = id; 15 | } 16 | 17 | public short? Id { get; set; } 18 | public string Name { get; set; } 19 | public short? ResourceCategoryId { get; set; } 20 | 21 | public virtual ResourceCategory ResourceCategoryFk { get; set; } 22 | public virtual Collection ResourceWatchList { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/ResourceCategory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using TheWatcher.Domain.Core.Common; 3 | 4 | namespace TheWatcher.Domain.Core.Models 5 | { 6 | public partial class ResourceCategory : Entity 7 | { 8 | public ResourceCategory() 9 | { 10 | } 11 | 12 | public ResourceCategory(short? id) 13 | { 14 | Id = id; 15 | } 16 | 17 | public short? Id { get; set; } 18 | public string Name { get; set; } 19 | public short? WatcherId { get; set; } 20 | 21 | public virtual Watcher WatcherFk { get; set; } 22 | public virtual Collection ResourceList { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/ResourceWatch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using TheWatcher.Domain.Core.Common; 3 | 4 | namespace TheWatcher.Domain.Core.Models 5 | { 6 | public partial class ResourceWatch : Entity 7 | { 8 | public ResourceWatch() 9 | { 10 | } 11 | 12 | public ResourceWatch(short? id) 13 | { 14 | Id = id; 15 | } 16 | 17 | public short? Id { get; set; } 18 | public short? ResourceId { get; set; } 19 | public short? EnvironmentId { get; set; } 20 | public bool? Successful { get; set; } 21 | public int? WatchCount { get; set; } 22 | public DateTime? LastWatch { get; set; } 23 | public int? Interval { get; set; } 24 | public string Description { get; set; } 25 | 26 | public virtual Resource ResourceFk { get; set; } 27 | public virtual Environment EnvironmentFk { get; set; } 28 | public virtual Collection ResourceWatchParameterList { get; set; } 29 | public virtual Collection ResourceWatchLogList { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/ResourceWatchLog.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Common; 2 | 3 | namespace TheWatcher.Domain.Core.Models 4 | { 5 | public class ResourceWatchLog : Entity 6 | { 7 | public ResourceWatchLog() 8 | { 9 | } 10 | 11 | public ResourceWatchLog(short? id) 12 | { 13 | Id = id; 14 | } 15 | 16 | public short? Id { get; set; } 17 | public short? ResourceWatchId { get; set; } 18 | public string AssemblyQualifiedName { get; set; } 19 | public string? ActionName { get; set; } 20 | public bool? Successful { get; set; } 21 | public string Message { get; set; } 22 | public string ErrorMessage { get; set; } 23 | 24 | public virtual ResourceWatch ResourceWatchFk { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/ResourceWatchParameter.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Common; 2 | 3 | namespace TheWatcher.Domain.Core.Models 4 | { 5 | public partial class ResourceWatchParameter : Entity 6 | { 7 | public ResourceWatchParameter() 8 | { 9 | } 10 | 11 | public ResourceWatchParameter(short? id) 12 | { 13 | Id = id; 14 | } 15 | 16 | public short? Id { get; set; } 17 | public short? ResourceWatchId { get; set; } 18 | public string Parameter { get; set; } 19 | public string Value { get; set; } 20 | public string Description { get; set; } 21 | 22 | public virtual ResourceWatch ResourceWatchFk { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/Watcher.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using TheWatcher.Domain.Core.Common; 3 | 4 | namespace TheWatcher.Domain.Core.Models 5 | { 6 | public partial class Watcher : Entity 7 | { 8 | public Watcher() 9 | { 10 | } 11 | 12 | public Watcher(short? id) 13 | { 14 | Id = id; 15 | } 16 | 17 | public short? Id { get; set; } 18 | public string Name { get; set; } 19 | public string Description { get; set; } 20 | public string ClassName { get; set; } 21 | public Guid? ClassGuid { get; set; } 22 | public string AssemblyQualifiedName { get; set; } 23 | 24 | public virtual Collection WatcherParameterList { get; set; } 25 | public virtual Collection ResourceCategoryList { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/Models/WatcherParameter.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Domain.Core.Common; 2 | 3 | namespace TheWatcher.Domain.Core.Models 4 | { 5 | public partial class WatcherParameter : Entity 6 | { 7 | public WatcherParameter() 8 | { 9 | } 10 | 11 | public WatcherParameter(short? id) 12 | { 13 | Id = id; 14 | } 15 | 16 | public short? Id { get; set; } 17 | public short? WatcherId { get; set; } 18 | public string Parameter { get; set; } 19 | public string Value { get; set; } 20 | public bool? IsDefault { get; set; } 21 | public string Description { get; set; } 22 | 23 | public virtual Watcher WatcherFk { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/QueryModels/ResourceQueryModel.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Domain.Core.QueryModels 2 | { 3 | public class ResourceQueryModel 4 | { 5 | public short? Id { get; set; } 6 | public string Name { get; set; } 7 | public short? ResourceCategoryId { get; set; } 8 | public string ResourceCategory { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/QueryModels/ResourceWatchQueryModel.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Domain.Core.QueryModels 2 | { 3 | public class ResourceWatchQueryModel 4 | { 5 | public short? Id { get; set; } 6 | public short? ResourceId { get; set; } 7 | public string Resource { get; set; } 8 | public short? ResourceCategoryId { get; set; } 9 | public string ResourceCategory { get; set; } 10 | public string AssemblyQualifiedName { get; set; } 11 | public short? EnvironmentId { get; set; } 12 | public string Environment { get; set; } 13 | public bool? Successful { get; set; } 14 | public int? WatchCount { get; set; } 15 | public DateTime? LastWatch { get; set; } 16 | public double? Interval { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/QueryModels/WatcherQueryModel.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Domain.Core.QueryModels 2 | { 3 | public class WatcherQueryModel 4 | { 5 | public short? Id { get; set; } 6 | public string Name { get; set; } 7 | public string Description { get; set; } 8 | public string ClassName { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/TheWatcher.Domain.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/TheWatcherDbContext.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Microsoft.EntityFrameworkCore; 3 | using TheWatcher.Domain.Core.Models; 4 | using Environment = TheWatcher.Domain.Core.Models.Environment; 5 | 6 | namespace TheWatcher.Domain.Core 7 | { 8 | public class TheWatcherDbContext : DbContext 9 | { 10 | public TheWatcherDbContext(DbContextOptions options) 11 | : base(options) 12 | { 13 | } 14 | 15 | public DbSet Watcher { get; set; } 16 | public DbSet WatcherParameter { get; set; } 17 | public DbSet ResourceCategory { get; set; } 18 | public DbSet Resource { get; set; } 19 | public DbSet Environment { get; set; } 20 | public DbSet ResourceWatch { get; set; } 21 | public DbSet ResourceWatchParameter { get; set; } 22 | public DbSet ResourceWatchLog { get; set; } 23 | 24 | protected override void OnModelCreating(ModelBuilder modelBuilder) 25 | { 26 | modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); 27 | 28 | base.OnModelCreating(modelBuilder); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Domain.Core/TheWatcherDbContextQueries.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using TheWatcher.Domain.Core.Models; 3 | using TheWatcher.Domain.Core.QueryModels; 4 | 5 | namespace TheWatcher.Domain.Core 6 | { 7 | public static class TheWatcherDbContextQueries 8 | { 9 | public static IQueryable GetWatchers(this TheWatcherDbContext ctx) 10 | { 11 | var query = 12 | from watcher in ctx.Watcher 13 | select new WatcherQueryModel 14 | { 15 | Id = watcher.Id, 16 | Name = watcher.Name, 17 | Description = watcher.Description, 18 | ClassName = watcher.ClassName 19 | }; 20 | 21 | return query; 22 | } 23 | 24 | public static IQueryable GetResources(this TheWatcherDbContext ctx) 25 | { 26 | var query = 27 | from resource in ctx.Resource 28 | join category in ctx.ResourceCategory on resource.ResourceCategoryId equals category.Id 29 | select new ResourceQueryModel 30 | { 31 | Id = resource.Id, 32 | Name = resource.Name, 33 | ResourceCategoryId = resource.ResourceCategoryId, 34 | ResourceCategory = category.Name 35 | }; 36 | 37 | return query; 38 | } 39 | 40 | public static IQueryable GetResourceWatchItems(this TheWatcherDbContext ctx) 41 | { 42 | var query = 43 | from resourceWatch in ctx.ResourceWatch 44 | join resource in ctx.Resource on resourceWatch.ResourceId equals resource.Id 45 | join resourceCategory in ctx.ResourceCategory on resource.ResourceCategoryId equals resourceCategory.Id 46 | join watcher in ctx.Watcher on resourceCategory.WatcherId equals watcher.Id 47 | join environment in ctx.Environment on resourceWatch.EnvironmentId equals environment.Id 48 | where resourceWatch.Active == true 49 | select new ResourceWatchQueryModel 50 | { 51 | Id = resourceWatch.Id, 52 | ResourceId = resourceWatch.ResourceId, 53 | Resource = resource.Name, 54 | ResourceCategoryId = resource.Id, 55 | ResourceCategory = resourceCategory.Name, 56 | AssemblyQualifiedName = watcher.AssemblyQualifiedName, 57 | EnvironmentId = environment.Id, 58 | Environment = environment.Name, 59 | Successful = resourceWatch.Successful, 60 | WatchCount = resourceWatch.WatchCount, 61 | LastWatch = resourceWatch.LastWatch, 62 | Interval = resourceWatch.Interval 63 | }; 64 | 65 | return query; 66 | } 67 | 68 | public static async Task GetWatcherAsync(this TheWatcherDbContext ctx, short? id) 69 | => await ctx.Watcher.Include(e => e.WatcherParameterList).FirstOrDefaultAsync(item => item.Id == id); 70 | 71 | public static async Task GetResourceAsync(this TheWatcherDbContext ctx, short? id) 72 | { 73 | return await ctx 74 | .Resource 75 | .Include(e => e.ResourceCategoryFk.WatcherFk) 76 | .Include(e => e.ResourceWatchList) 77 | .ThenInclude(e => e.EnvironmentFk) 78 | .Include(e => e.ResourceWatchList) 79 | .ThenInclude(e => e.ResourceWatchParameterList) 80 | .FirstOrDefaultAsync(item => item.Id == id) 81 | ; 82 | } 83 | 84 | public static async Task GetResourceWatchAsync(this TheWatcherDbContext ctx, short? id) 85 | => await ctx.ResourceWatch.FirstOrDefaultAsync(item => item.Id == id); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/Contracts/IWatcher.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Library.Core.Contracts 2 | { 3 | public interface IWatcher 4 | { 5 | Guid Guid { get; } 6 | 7 | string ActionName { get; } 8 | 9 | Task WatchAsync(WatcherParam parameter); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/Contracts/IWatcherResult.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Library.Core.Contracts 2 | { 3 | public interface IWatcherResult 4 | { 5 | bool IsSuccess { get; set; } 6 | DateTime LastWatch { get; set; } 7 | string Message { get; set; } 8 | string ErrorMessage { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "TheWatcher.Library.Core": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:60390;http://localhost:60392" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/TheWatcher.Library.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/WatcherParam.cs: -------------------------------------------------------------------------------- 1 | namespace TheWatcher.Library.Core 2 | { 3 | public class WatcherParam 4 | { 5 | public const string IPAddress = "IPAddress"; 6 | public const string ConnectionString = "ConnectionString"; 7 | public const string DatabaseName = "DatabaseName"; 8 | public const string Endpoint = "Endpoint"; 9 | public const string HostName = "HostName"; 10 | 11 | public WatcherParam() 12 | { 13 | Values = new Dictionary(); 14 | } 15 | 16 | public WatcherParam(IDictionary dictionary) 17 | { 18 | Values = dictionary; 19 | } 20 | 21 | public IDictionary Values { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Source/TheWatcher.Library.Core/WatcherResult.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Library.Core.Contracts; 2 | 3 | namespace TheWatcher.Library.Core 4 | { 5 | public class WatcherResult : IWatcherResult 6 | { 7 | public WatcherResult() 8 | { 9 | LastWatch = DateTime.Now; 10 | } 11 | 12 | public bool IsSuccess { get; set; } 13 | public DateTime LastWatch { get; set; } 14 | public string Message { get; set; } 15 | public string ErrorMessage { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/TheWatcher.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32825.248 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Watchers", "Watchers", "{0B65BF35-BA72-414E-B710-FC83187E0605}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Watchers.PingWatcher", "Watchers\TheWatcher.Watchers.PingWatcher\TheWatcher.Watchers.PingWatcher.csproj", "{FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Watchers.SqlServer", "Watchers\TheWatcher.Watchers.SqlServer\TheWatcher.Watchers.SqlServer.csproj", "{11169F75-5CF6-40D8-9C46-6096DF1F92A7}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{E6A8F357-C5F2-414B-9814-3C00FC3183FD}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Domain.Core", "Source\TheWatcher.Domain.Core\TheWatcher.Domain.Core.csproj", "{DB253CC8-5EB5-4156-B6EF-839DC53E4E14}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Library.Core", "Source\TheWatcher.Library.Core\TheWatcher.Library.Core.csproj", "{E0F9425B-8D58-4D02-AF87-0631FA249FF8}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.API.Common", "Source\TheWatcher.API.Common\TheWatcher.API.Common.csproj", "{9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.API.Monitor", "Source\TheWatcher.API.Monitor\TheWatcher.API.Monitor.csproj", "{E049FF90-F1C2-4BCC-869D-456A21B05E78}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.API.Panel", "Source\TheWatcher.API.Panel\TheWatcher.API.Panel.csproj", "{BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Seed", "Seed", "{03D1349F-22A8-43F6-B0E8-18B1EBBCD8CD}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Seed.Db", "Seed\TheWatcher.Seed.Db\TheWatcher.Seed.Db.csproj", "{2D25C152-DC8A-4F3F-9C79-FB4596F967DE}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Watchers.MongoDB", "Watchers\TheWatcher.Watchers.MongoDB\TheWatcher.Watchers.MongoDB.csproj", "{6F6B346D-B4A5-4550-8D6E-0583D33EA63A}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Watchers.RabbitMQ", "Watchers\TheWatcher.Watchers.RabbitMQ\TheWatcher.Watchers.RabbitMQ.csproj", "{2EBEE05B-BD93-4A58-9286-69A577017157}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheWatcher.Watchers.PostgreSQL", "Watchers\TheWatcher.Watchers.PostgreSQL\TheWatcher.Watchers.PostgreSQL.csproj", "{7F949F6D-90E5-4203-B8D9-0904D8F9FB78}" 33 | EndProject 34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheWatcher.Watchers.RESTfulGet", "Watchers\TheWatcher.Watchers.RESTfulGet\TheWatcher.Watchers.RESTfulGet.csproj", "{37E0A327-A31E-42BA-AE16-9F3B9CF2A896}" 35 | EndProject 36 | Global 37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 38 | Debug|Any CPU = Debug|Any CPU 39 | Release|Any CPU = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {11169F75-5CF6-40D8-9C46-6096DF1F92A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {11169F75-5CF6-40D8-9C46-6096DF1F92A7}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {11169F75-5CF6-40D8-9C46-6096DF1F92A7}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {11169F75-5CF6-40D8-9C46-6096DF1F92A7}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {DB253CC8-5EB5-4156-B6EF-839DC53E4E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {DB253CC8-5EB5-4156-B6EF-839DC53E4E14}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {DB253CC8-5EB5-4156-B6EF-839DC53E4E14}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {DB253CC8-5EB5-4156-B6EF-839DC53E4E14}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {E0F9425B-8D58-4D02-AF87-0631FA249FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {E0F9425B-8D58-4D02-AF87-0631FA249FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {E0F9425B-8D58-4D02-AF87-0631FA249FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {E0F9425B-8D58-4D02-AF87-0631FA249FF8}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {E049FF90-F1C2-4BCC-869D-456A21B05E78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {E049FF90-F1C2-4BCC-869D-456A21B05E78}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {E049FF90-F1C2-4BCC-869D-456A21B05E78}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {E049FF90-F1C2-4BCC-869D-456A21B05E78}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {2D25C152-DC8A-4F3F-9C79-FB4596F967DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {2D25C152-DC8A-4F3F-9C79-FB4596F967DE}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {2D25C152-DC8A-4F3F-9C79-FB4596F967DE}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {2D25C152-DC8A-4F3F-9C79-FB4596F967DE}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {6F6B346D-B4A5-4550-8D6E-0583D33EA63A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {6F6B346D-B4A5-4550-8D6E-0583D33EA63A}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {6F6B346D-B4A5-4550-8D6E-0583D33EA63A}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {6F6B346D-B4A5-4550-8D6E-0583D33EA63A}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {2EBEE05B-BD93-4A58-9286-69A577017157}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {2EBEE05B-BD93-4A58-9286-69A577017157}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {2EBEE05B-BD93-4A58-9286-69A577017157}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {2EBEE05B-BD93-4A58-9286-69A577017157}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {7F949F6D-90E5-4203-B8D9-0904D8F9FB78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {7F949F6D-90E5-4203-B8D9-0904D8F9FB78}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {7F949F6D-90E5-4203-B8D9-0904D8F9FB78}.Release|Any CPU.ActiveCfg = Release|Any CPU 85 | {7F949F6D-90E5-4203-B8D9-0904D8F9FB78}.Release|Any CPU.Build.0 = Release|Any CPU 86 | {37E0A327-A31E-42BA-AE16-9F3B9CF2A896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {37E0A327-A31E-42BA-AE16-9F3B9CF2A896}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {37E0A327-A31E-42BA-AE16-9F3B9CF2A896}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {37E0A327-A31E-42BA-AE16-9F3B9CF2A896}.Release|Any CPU.Build.0 = Release|Any CPU 90 | EndGlobalSection 91 | GlobalSection(SolutionProperties) = preSolution 92 | HideSolutionNode = FALSE 93 | EndGlobalSection 94 | GlobalSection(NestedProjects) = preSolution 95 | {FC3591AE-B2D9-43E6-8D60-3DEDF7B4A73D} = {0B65BF35-BA72-414E-B710-FC83187E0605} 96 | {11169F75-5CF6-40D8-9C46-6096DF1F92A7} = {0B65BF35-BA72-414E-B710-FC83187E0605} 97 | {DB253CC8-5EB5-4156-B6EF-839DC53E4E14} = {E6A8F357-C5F2-414B-9814-3C00FC3183FD} 98 | {E0F9425B-8D58-4D02-AF87-0631FA249FF8} = {E6A8F357-C5F2-414B-9814-3C00FC3183FD} 99 | {9F5A4C67-ADF7-4896-9FA1-5C39C0CDBA8D} = {E6A8F357-C5F2-414B-9814-3C00FC3183FD} 100 | {E049FF90-F1C2-4BCC-869D-456A21B05E78} = {E6A8F357-C5F2-414B-9814-3C00FC3183FD} 101 | {BE2F5A9C-A3AF-41E9-A7E0-BFDAF2F4D707} = {E6A8F357-C5F2-414B-9814-3C00FC3183FD} 102 | {2D25C152-DC8A-4F3F-9C79-FB4596F967DE} = {03D1349F-22A8-43F6-B0E8-18B1EBBCD8CD} 103 | {6F6B346D-B4A5-4550-8D6E-0583D33EA63A} = {0B65BF35-BA72-414E-B710-FC83187E0605} 104 | {2EBEE05B-BD93-4A58-9286-69A577017157} = {0B65BF35-BA72-414E-B710-FC83187E0605} 105 | {7F949F6D-90E5-4203-B8D9-0904D8F9FB78} = {0B65BF35-BA72-414E-B710-FC83187E0605} 106 | {37E0A327-A31E-42BA-AE16-9F3B9CF2A896} = {0B65BF35-BA72-414E-B710-FC83187E0605} 107 | EndGlobalSection 108 | GlobalSection(ExtensibilityGlobals) = postSolution 109 | SolutionGuid = {09D2FE22-C83D-44AE-85D6-DD48782926CA} 110 | EndGlobalSection 111 | EndGlobal 112 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.MongoDB/MongoDBWatcher.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using TheWatcher.Library.Core; 3 | using TheWatcher.Library.Core.Contracts; 4 | 5 | namespace TheWatcher.Watchers.MongoDB 6 | { 7 | public sealed class MongoDBWatcher : IWatcher 8 | { 9 | static readonly Guid ClassGuid = new("5F766F68-1554-4F9C-9098-61CA3BA5A0D2"); 10 | 11 | public Guid Guid 12 | => ClassGuid; 13 | 14 | public string ActionName 15 | => "OpenDatabaseConnection"; 16 | 17 | public async Task WatchAsync(WatcherParam parameter) 18 | { 19 | if (parameter == null) 20 | throw new ArgumentNullException(nameof(parameter)); 21 | 22 | var result = new WatcherResult(); 23 | 24 | try 25 | { 26 | var client = new MongoClient(parameter.Values[WatcherParam.ConnectionString]); 27 | 28 | await client.StartSessionAsync(); 29 | 30 | var database = client.GetDatabase(parameter.Values[WatcherParam.DatabaseName]); 31 | 32 | result.IsSuccess = true; 33 | } 34 | catch (Exception ex) 35 | { 36 | result.Message = ex.Message; 37 | result.ErrorMessage = ex.ToString(); 38 | } 39 | 40 | return result; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.MongoDB/TheWatcher.Watchers.MongoDB.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.PingWatcher/PingWatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Net.NetworkInformation; 2 | using TheWatcher.Library.Core; 3 | using TheWatcher.Library.Core.Contracts; 4 | 5 | namespace TheWatcher.Watchers.PingWatcher 6 | { 7 | public sealed class PingWatcher : IWatcher 8 | { 9 | static readonly Guid ClassGuid = new("75B0AD20-A454-41E9-9FDA-AD065A7A95DD"); 10 | 11 | public Guid Guid 12 | => ClassGuid; 13 | 14 | public string ActionName 15 | => "Ping"; 16 | 17 | public async Task WatchAsync(WatcherParam parameter) 18 | { 19 | var result = new WatcherResult(); 20 | 21 | try 22 | { 23 | var reply = await new Ping().SendPingAsync(parameter.Values[WatcherParam.IPAddress]); 24 | 25 | result.IsSuccess = reply.Status == IPStatus.Success; 26 | } 27 | catch(Exception ex) 28 | { 29 | result.Message = ex.Message; 30 | result.ErrorMessage = ex.ToString(); 31 | } 32 | 33 | return result; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.PingWatcher/TheWatcher.Watchers.PingWatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.PostgreSQL/PostgreSQLDatabaseWatcher.cs: -------------------------------------------------------------------------------- 1 | using Npgsql; 2 | using TheWatcher.Library.Core; 3 | using TheWatcher.Library.Core.Contracts; 4 | 5 | namespace TheWatcher.Watchers.PostgreSQL 6 | { 7 | public sealed class PostgreSQLDatabaseWatcher : IWatcher 8 | { 9 | static readonly Guid ClassGuid = new("A7C757FC-9DA2-4563-880B-15D93693DDC6"); 10 | 11 | public Guid Guid 12 | => ClassGuid; 13 | 14 | public string ActionName 15 | => "OpenDatabaseConnection"; 16 | 17 | public async Task WatchAsync(WatcherParam parameter) 18 | { 19 | if (parameter == null) 20 | throw new ArgumentNullException(nameof(parameter)); 21 | 22 | var result = new WatcherResult(); 23 | 24 | using var connection = new NpgsqlConnection(parameter.Values[WatcherParam.ConnectionString]); 25 | 26 | try 27 | { 28 | await connection.OpenAsync(); 29 | 30 | result.IsSuccess = true; 31 | } 32 | catch (Exception ex) 33 | { 34 | result.Message = ex.Message; 35 | result.ErrorMessage = ex.ToString(); 36 | } 37 | 38 | return result; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.PostgreSQL/TheWatcher.Watchers.PostgreSQL.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.RESTfulGet/RESTfulGetWatcher.cs: -------------------------------------------------------------------------------- 1 | using TheWatcher.Library.Core; 2 | using TheWatcher.Library.Core.Contracts; 3 | 4 | namespace TheWatcher.Watchers.RESTfulGet 5 | { 6 | public sealed class RESTfulGetWatcher : IWatcher 7 | { 8 | static readonly Guid ClassGuid = new("5A4FB948-176D-4645-A4EA-47FF6844E56A"); 9 | 10 | public Guid Guid 11 | => ClassGuid; 12 | 13 | public string ActionName 14 | => "RESTfulGet"; 15 | 16 | public async Task WatchAsync(WatcherParam parameter) 17 | { 18 | var result = new WatcherResult(); 19 | 20 | try 21 | { 22 | using var client = new HttpClient(); 23 | 24 | var response = await client.GetAsync(parameter.Values[WatcherParam.Endpoint]); 25 | response.EnsureSuccessStatusCode(); 26 | 27 | result.IsSuccess = true; 28 | } 29 | catch (Exception ex) 30 | { 31 | result.Message = ex.Message; 32 | result.ErrorMessage = ex.ToString(); 33 | } 34 | 35 | return result; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.RESTfulGet/TheWatcher.Watchers.RESTfulGet.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.RabbitMQ/RabbitMQWatcher.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using TheWatcher.Library.Core; 3 | using TheWatcher.Library.Core.Contracts; 4 | 5 | namespace TheWatcher.Watchers.RabbitMQ 6 | { 7 | public sealed class RabbitMQWatcher : IWatcher 8 | { 9 | static readonly Guid ClassGuid = new("EC0CAAF2-436C-4FD5-AEE3-7BD8E27F714B"); 10 | 11 | public Guid Guid 12 | => ClassGuid; 13 | 14 | public string ActionName 15 | => "CreateBrokerConnection"; 16 | 17 | public async Task WatchAsync(WatcherParam parameter) 18 | { 19 | if (parameter == null) 20 | throw new ArgumentNullException(nameof(parameter)); 21 | 22 | var result = new WatcherResult(); 23 | 24 | try 25 | { 26 | var factory = new ConnectionFactory 27 | { 28 | HostName = parameter.Values[WatcherParam.HostName] 29 | }; 30 | 31 | using var connection = factory.CreateConnection(); 32 | using var channel = connection.CreateModel(); 33 | 34 | result.IsSuccess = true; 35 | } 36 | catch (Exception ex) 37 | { 38 | result.Message = ex.Message; 39 | result.ErrorMessage = ex.ToString(); 40 | } 41 | 42 | return await Task.FromResult(result); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.RabbitMQ/TheWatcher.Watchers.RabbitMQ.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.SqlServer/SqlServerDatabaseWatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Data.SqlClient; 2 | using TheWatcher.Library.Core; 3 | using TheWatcher.Library.Core.Contracts; 4 | 5 | namespace TheWatcher.Watchers.SqlServer 6 | { 7 | public sealed class SqlServerDatabaseWatcher : IWatcher 8 | { 9 | static readonly Guid ClassGuid = new("A1059C4E-1615-49EB-993D-274458DD212B"); 10 | 11 | public Guid Guid 12 | => ClassGuid; 13 | 14 | public string ActionName 15 | => "OpenDatabaseConnection"; 16 | 17 | public async Task WatchAsync(WatcherParam parameter) 18 | { 19 | if (parameter == null) 20 | throw new ArgumentNullException(nameof(parameter)); 21 | 22 | var result = new WatcherResult(); 23 | 24 | using var connection = new SqlConnection(parameter.Values[WatcherParam.ConnectionString]); 25 | 26 | try 27 | { 28 | await connection.OpenAsync(); 29 | 30 | result.IsSuccess = true; 31 | } 32 | catch (Exception ex) 33 | { 34 | result.Message = ex.Message; 35 | result.ErrorMessage = ex.ToString(); 36 | } 37 | 38 | return result; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Source/Backend/TheWatcher/Watchers/TheWatcher.Watchers.SqlServer/TheWatcher.Watchers.SqlServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | disable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/README.md: -------------------------------------------------------------------------------- 1 | # ThewatcherGui 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 14.2.9. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "thewatcher-gui": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "dist/thewatcher-gui", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": "src/polyfills.ts", 20 | "tsConfig": "tsconfig.app.json", 21 | "assets": [ 22 | "src/favicon.ico", 23 | "src/assets" 24 | ], 25 | "styles": [ 26 | "@angular/material/prebuilt-themes/pink-bluegrey.css", 27 | "src/styles.css" 28 | ], 29 | "scripts": [] 30 | }, 31 | "configurations": { 32 | "production": { 33 | "budgets": [ 34 | { 35 | "type": "initial", 36 | "maximumWarning": "500kb", 37 | "maximumError": "1mb" 38 | }, 39 | { 40 | "type": "anyComponentStyle", 41 | "maximumWarning": "2kb", 42 | "maximumError": "4kb" 43 | } 44 | ], 45 | "fileReplacements": [ 46 | { 47 | "replace": "src/environments/environment.ts", 48 | "with": "src/environments/environment.prod.ts" 49 | } 50 | ], 51 | "outputHashing": "all" 52 | }, 53 | "development": { 54 | "buildOptimizer": false, 55 | "optimization": false, 56 | "vendorChunk": true, 57 | "extractLicenses": false, 58 | "sourceMap": true, 59 | "namedChunks": true 60 | } 61 | }, 62 | "defaultConfiguration": "production" 63 | }, 64 | "serve": { 65 | "options": { 66 | "port": 13010 67 | }, 68 | "builder": "@angular-devkit/build-angular:dev-server", 69 | "configurations": { 70 | "production": { 71 | "browserTarget": "thewatcher-gui:build:production" 72 | }, 73 | "development": { 74 | "browserTarget": "thewatcher-gui:build:development" 75 | } 76 | }, 77 | "defaultConfiguration": "development" 78 | }, 79 | "extract-i18n": { 80 | "builder": "@angular-devkit/build-angular:extract-i18n", 81 | "options": { 82 | "browserTarget": "thewatcher-gui:build" 83 | } 84 | }, 85 | "test": { 86 | "builder": "@angular-devkit/build-angular:karma", 87 | "options": { 88 | "main": "src/test.ts", 89 | "polyfills": "src/polyfills.ts", 90 | "tsConfig": "tsconfig.spec.json", 91 | "karmaConfig": "karma.conf.js", 92 | "assets": [ 93 | "src/favicon.ico", 94 | "src/assets" 95 | ], 96 | "styles": [ 97 | "@angular/material/prebuilt-themes/pink-bluegrey.css", 98 | "src/styles.css" 99 | ], 100 | "scripts": [] 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/thewatcher-gui'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "thewatcher-gui", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^15.1.0", 14 | "@angular/cdk": "^15.1.0", 15 | "@angular/common": "^15.1.0", 16 | "@angular/compiler": "^15.1.0", 17 | "@angular/core": "^15.1.0", 18 | "@angular/forms": "^15.1.0", 19 | "@angular/material": "^15.1.0", 20 | "@angular/platform-browser": "^15.1.0", 21 | "@angular/platform-browser-dynamic": "^15.1.0", 22 | "@angular/router": "^15.1.0", 23 | "@aspnet/signalr": "^1.0.27", 24 | "rxjs": "~7.5.0", 25 | "tslib": "^2.3.0", 26 | "zone.js": "~0.11.4" 27 | }, 28 | "devDependencies": { 29 | "@angular-devkit/build-angular": "^15.1.1", 30 | "@angular/cli": "~15.1.1", 31 | "@angular/compiler-cli": "^15.1.0", 32 | "@types/jasmine": "~4.0.0", 33 | "jasmine-core": "~4.3.0", 34 | "karma": "~6.4.0", 35 | "karma-chrome-launcher": "~3.1.0", 36 | "karma-coverage": "~2.2.0", 37 | "karma-jasmine": "~5.1.0", 38 | "karma-jasmine-html-reporter": "~2.0.0", 39 | "typescript": "~4.9.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | import { HomeComponent } from './components/home/home.component'; 5 | import { WatcherListComponent } from './components/watcher-list/watcher-list.component'; 6 | import { ResourceListComponent } from './components/resource-list/resource-list.component'; 7 | 8 | const routes: Routes = [ 9 | { path: '', component: HomeComponent }, 10 | { path: 'watcher', component: WatcherListComponent }, 11 | { path: 'resource', component: ResourceListComponent } 12 | ]; 13 | 14 | @NgModule({ 15 | imports: [RouterModule.forRoot(routes)], 16 | exports: [RouterModule] 17 | }) 18 | export class AppRoutingModule { } 19 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | .sidenav-container { 2 | height: 100%; 3 | } 4 | 5 | .sidenav { 6 | width: 200px; 7 | } 8 | 9 | .sidenav .mat-toolbar { 10 | background: inherit; 11 | } 12 | 13 | .mat-toolbar.mat-primary { 14 | position: sticky; 15 | top: 0; 16 | z-index: 1; 17 | } 18 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | Menu 5 | 6 | Home 7 | Watchers 8 | Resources 9 | 10 | 11 | 12 | 13 | 17 | The Watcher 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'thewatcher-gui'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('thewatcher-gui'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement as HTMLElement; 33 | expect(compiled.querySelector('.content span')?.textContent).toContain('thewatcher-gui app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { Observable } from 'rxjs'; 4 | import { map, shareReplay } from 'rxjs/operators'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.css'] 10 | }) 11 | export class AppComponent { 12 | title = 'The Watcher'; 13 | 14 | isHandset$: Observable = this.breakpointObserver.observe(Breakpoints.Handset) 15 | .pipe( 16 | map(result => result.matches), 17 | shareReplay() 18 | ); 19 | 20 | constructor(private breakpointObserver: BreakpointObserver) {} 21 | } 22 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppRoutingModule } from './app-routing.module'; 5 | import { AppComponent } from './app.component'; 6 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 7 | import { LayoutModule } from '@angular/cdk/layout'; 8 | import { MatToolbarModule } from '@angular/material/toolbar'; 9 | import { MatButtonModule } from '@angular/material/button'; 10 | import { MatSidenavModule } from '@angular/material/sidenav'; 11 | import { MatIconModule } from '@angular/material/icon'; 12 | import { MatListModule } from '@angular/material/list'; 13 | import { MatGridListModule } from '@angular/material/grid-list'; 14 | import { MatCardModule } from '@angular/material/card'; 15 | import { MatMenuModule } from '@angular/material/menu'; 16 | import { HomeComponent } from './components/home/home.component'; 17 | import { HttpClientModule } from '@angular/common/http'; 18 | import { WatcherListComponent } from './components/watcher-list/watcher-list.component'; 19 | import { MatTableModule } from '@angular/material/table'; 20 | import { MatPaginatorModule } from '@angular/material/paginator'; 21 | import { MatSortModule } from '@angular/material/sort'; 22 | import { ResourceListComponent } from './components/resource-list/resource-list.component'; 23 | 24 | @NgModule({ 25 | declarations: [ 26 | AppComponent, 27 | HomeComponent, 28 | WatcherListComponent, 29 | ResourceListComponent 30 | ], 31 | imports: [ 32 | BrowserModule, 33 | AppRoutingModule, 34 | BrowserAnimationsModule, 35 | HttpClientModule, 36 | LayoutModule, 37 | MatToolbarModule, 38 | MatButtonModule, 39 | MatSidenavModule, 40 | MatIconModule, 41 | MatListModule, 42 | MatGridListModule, 43 | MatCardModule, 44 | MatMenuModule, 45 | MatTableModule, 46 | MatPaginatorModule, 47 | MatSortModule 48 | ], 49 | providers: [], 50 | bootstrap: [AppComponent] 51 | }) 52 | export class AppModule { } 53 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/home/home.component.css: -------------------------------------------------------------------------------- 1 | .grid-container { 2 | margin: 20px; 3 | } 4 | 5 | .dashboard-card { 6 | position: absolute; 7 | top: 15px; 8 | left: 15px; 9 | right: 15px; 10 | bottom: 15px; 11 | } 12 | 13 | .more-button { 14 | position: absolute; 15 | top: 5px; 16 | right: 10px; 17 | } 18 | 19 | .dashboard-card-content { 20 | text-align: center; 21 | } 22 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Dashboard

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 23 | 28 | 31 | 34 | 37 | 38 | 39 |
ResourceEnvironmentStatusWatch countLast watchInterval
18 | {{ item.resource }} 19 | 21 | {{ item.environment }} 22 | 24 | 27 | 29 | {{ item.watchCount }} 30 | 32 | {{ item.lastWatch | date: 'long' }} 33 | 35 | {{ item.interval }} 36 |
40 | 41 | 62 |
63 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { map } from 'rxjs/operators'; 3 | import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout'; 4 | import * as signalR from '@aspnet/signalr'; 5 | import { MonitorClientService, ResourceWatchItemModel } from 'src/app/services/monitor-client.service'; 6 | import { ListResponse } from 'src/app/services/common'; 7 | import { MONITOR_API_ENDPOINT } from 'src/settings'; 8 | 9 | @Component({ 10 | selector: 'app-home', 11 | templateUrl: './home.component.html', 12 | styleUrls: ['./home.component.css'] 13 | }) 14 | export class HomeComponent implements OnInit { 15 | /** Based on the screen size, switch from standard to one column per row */ 16 | cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe( 17 | map(({ matches }) => { 18 | if (matches) { 19 | return [ 20 | { title: 'Card 1', cols: 1, rows: 1 }, 21 | { title: 'Card 2', cols: 1, rows: 1 }, 22 | { title: 'Card 3', cols: 1, rows: 1 }, 23 | { title: 'Card 4', cols: 1, rows: 1 } 24 | ]; 25 | } 26 | 27 | return [ 28 | { title: 'Card 1', cols: 2, rows: 1 }, 29 | { title: 'Card 2', cols: 1, rows: 1 }, 30 | { title: 'Card 3', cols: 1, rows: 2 }, 31 | { title: 'Card 4', cols: 1, rows: 1 } 32 | ]; 33 | }) 34 | ); 35 | 36 | private hubEndpoint!: string; 37 | 38 | constructor(private breakpointObserver: BreakpointObserver, private monitorClient: MonitorClientService) { 39 | this.hubEndpoint = `${MONITOR_API_ENDPOINT}/monitorhub`; 40 | } 41 | 42 | private hubConnection!: signalR.HubConnection; 43 | public response!: ListResponse; 44 | 45 | ngOnInit(): void { 46 | 47 | this.monitorClient.getMonitor().subscribe(result => { 48 | this.response = result; 49 | }); 50 | 51 | this.hubConnection = new signalR 52 | .HubConnectionBuilder() 53 | .configureLogging(signalR.LogLevel.Debug) 54 | .withUrl(this.hubEndpoint) 55 | .build() 56 | ; 57 | 58 | this 59 | .hubConnection 60 | .start() 61 | .then(() => { 62 | console.log('Connection started!'); 63 | }) 64 | .catch(err => console.log(`Error while starting connection: ${err}`)) 65 | ; 66 | 67 | this.hubConnection.on('receiveResourceWatch', (notification: ResourceWatchArg) => { 68 | console.log(notification); 69 | 70 | this.response.model.forEach((item) => { 71 | if (item.resourceId == notification.resourceId && item.environmentId == notification.environmentId) { 72 | item.successful = notification.isSuccess; 73 | item.watchCount += 1; 74 | } 75 | }); 76 | }); 77 | } 78 | } 79 | 80 | class ResourceWatchArg { 81 | public resource!: string; 82 | public resourceId!: number; 83 | public environmentId!: number; 84 | public environment!: string; 85 | public isSuccess!: boolean; 86 | } 87 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/resource-list/resource-list-datasource.ts: -------------------------------------------------------------------------------- 1 | import { DataSource } from '@angular/cdk/collections'; 2 | import { MatPaginator } from '@angular/material/paginator'; 3 | import { MatSort } from '@angular/material/sort'; 4 | import { map } from 'rxjs/operators'; 5 | import { Observable, of as observableOf, merge } from 'rxjs'; 6 | import { ResourceItemModel } from 'src/app/services/panel-client.service'; 7 | 8 | /** 9 | * Data source for the ResourceList view. This class should 10 | * encapsulate all logic for fetching and manipulating the displayed data 11 | * (including sorting, pagination, and filtering). 12 | */ 13 | export class ResourceListDataSource extends DataSource { 14 | data: ResourceItemModel[]; 15 | paginator: MatPaginator | undefined; 16 | sort: MatSort | undefined; 17 | 18 | constructor(data: ResourceItemModel[]) { 19 | super(); 20 | this.data = data; 21 | } 22 | 23 | /** 24 | * Connect this data source to the table. The table will only update when 25 | * the returned stream emits new items. 26 | * @returns A stream of the items to be rendered. 27 | */ 28 | connect(): Observable { 29 | if (this.paginator && this.sort) { 30 | // Combine everything that affects the rendered data into one update 31 | // stream for the data-table to consume. 32 | return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange) 33 | .pipe(map(() => { 34 | return this.getPagedData(this.getSortedData([...this.data ])); 35 | })); 36 | } else { 37 | throw Error('Please set the paginator and sort on the data source before connecting.'); 38 | } 39 | } 40 | 41 | /** 42 | * Called when the table is being destroyed. Use this function, to clean up 43 | * any open connections or free any held resources that were set up during connect. 44 | */ 45 | disconnect(): void {} 46 | 47 | /** 48 | * Paginate the data (client-side). If you're using server-side pagination, 49 | * this would be replaced by requesting the appropriate data from the server. 50 | */ 51 | private getPagedData(data: ResourceItemModel[]): ResourceItemModel[] { 52 | if (this.paginator) { 53 | const startIndex = this.paginator.pageIndex * this.paginator.pageSize; 54 | return data.splice(startIndex, this.paginator.pageSize); 55 | } else { 56 | return data; 57 | } 58 | } 59 | 60 | /** 61 | * Sort the data (client-side). If you're using server-side sorting, 62 | * this would be replaced by requesting the appropriate data from the server. 63 | */ 64 | private getSortedData(data: ResourceItemModel[]): ResourceItemModel[] { 65 | if (!this.sort || !this.sort.active || this.sort.direction === '') { 66 | return data; 67 | } 68 | 69 | return data.sort((a, b) => { 70 | const isAsc = this.sort?.direction === 'asc'; 71 | switch (this.sort?.active) { 72 | case 'resourceCategory': return compare(a.resourceCategory, b.resourceCategory, isAsc); 73 | case 'name': return compare(a.name, b.name, isAsc); 74 | case 'id': return compare(+a.id, +b.id, isAsc); 75 | default: return 0; 76 | } 77 | }); 78 | } 79 | } 80 | 81 | /** Simple sort comparator for example ID/Name columns (for client-side sorting). */ 82 | function compare(a: string | number, b: string | number, isAsc: boolean): number { 83 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 84 | } 85 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/resource-list/resource-list.component.css: -------------------------------------------------------------------------------- 1 | .full-width-table { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/resource-list/resource-list.component.html: -------------------------------------------------------------------------------- 1 |

Resources

2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
Id{{row.id}}Name{{row.name}}Resource Category{{row.resourceCategory}}
26 | 27 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/resource-list/resource-list.component.ts: -------------------------------------------------------------------------------- 1 | import { AfterViewInit, Component, ViewChild } from '@angular/core'; 2 | import { MatPaginator } from '@angular/material/paginator'; 3 | import { MatSort } from '@angular/material/sort'; 4 | import { MatTable } from '@angular/material/table'; 5 | import { ResourceListDataSource } from './resource-list-datasource'; 6 | import { PanelClientService, ResourceItemModel } from 'src/app/services/panel-client.service'; 7 | 8 | @Component({ 9 | selector: 'app-resource-list', 10 | templateUrl: './resource-list.component.html', 11 | styleUrls: ['./resource-list.component.css'] 12 | }) 13 | export class ResourceListComponent implements AfterViewInit { 14 | @ViewChild(MatPaginator) paginator!: MatPaginator; 15 | @ViewChild(MatSort) sort!: MatSort; 16 | @ViewChild(MatTable) table!: MatTable; 17 | dataSource!: ResourceListDataSource; 18 | 19 | displayedColumns = ['id', 'name', 'resourceCategory']; 20 | 21 | constructor(private panelClient: PanelClientService) { 22 | } 23 | 24 | ngAfterViewInit(): void { 25 | this.panelClient.getResources().subscribe(result => { 26 | this.dataSource = new ResourceListDataSource(result.model); 27 | this.dataSource.sort = this.sort; 28 | this.dataSource.paginator = this.paginator; 29 | this.table.dataSource = this.dataSource; 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/watcher-list/watcher-list-datasource.ts: -------------------------------------------------------------------------------- 1 | import { DataSource } from '@angular/cdk/collections'; 2 | import { MatPaginator } from '@angular/material/paginator'; 3 | import { MatSort } from '@angular/material/sort'; 4 | import { map } from 'rxjs/operators'; 5 | import { Observable, of as observableOf, merge } from 'rxjs'; 6 | import { WatcherItemModel } from 'src/app/services/panel-client.service'; 7 | 8 | /** 9 | * Data source for the WatcherList view. This class should 10 | * encapsulate all logic for fetching and manipulating the displayed data 11 | * (including sorting, pagination, and filtering). 12 | */ 13 | export class WatcherListDataSource extends DataSource { 14 | data: WatcherItemModel[]; 15 | paginator: MatPaginator | undefined; 16 | sort: MatSort | undefined; 17 | 18 | constructor(data: WatcherItemModel[]) { 19 | super(); 20 | this.data = data; 21 | } 22 | 23 | /** 24 | * Connect this data source to the table. The table will only update when 25 | * the returned stream emits new items. 26 | * @returns A stream of the items to be rendered. 27 | */ 28 | connect(): Observable { 29 | if (this.paginator && this.sort) { 30 | // Combine everything that affects the rendered data into one update 31 | // stream for the data-table to consume. 32 | return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange) 33 | .pipe(map(() => { 34 | return this.getPagedData(this.getSortedData([...this.data ])); 35 | })); 36 | } else { 37 | throw Error('Please set the paginator and sort on the data source before connecting.'); 38 | } 39 | } 40 | 41 | /** 42 | * Called when the table is being destroyed. Use this function, to clean up 43 | * any open connections or free any held resources that were set up during connect. 44 | */ 45 | disconnect(): void {} 46 | 47 | /** 48 | * Paginate the data (client-side). If you're using server-side pagination, 49 | * this would be replaced by requesting the appropriate data from the server. 50 | */ 51 | private getPagedData(data: WatcherItemModel[]): WatcherItemModel[] { 52 | if (this.paginator) { 53 | const startIndex = this.paginator.pageIndex * this.paginator.pageSize; 54 | return data.splice(startIndex, this.paginator.pageSize); 55 | } else { 56 | return data; 57 | } 58 | } 59 | 60 | /** 61 | * Sort the data (client-side). If you're using server-side sorting, 62 | * this would be replaced by requesting the appropriate data from the server. 63 | */ 64 | private getSortedData(data: WatcherItemModel[]): WatcherItemModel[] { 65 | if (!this.sort || !this.sort.active || this.sort.direction === '') { 66 | return data; 67 | } 68 | 69 | return data.sort((a, b) => { 70 | const isAsc = this.sort?.direction === 'asc'; 71 | switch (this.sort?.active) { 72 | case 'name': return compare(a.name, b.name, isAsc); 73 | case 'id': return compare(+a.id, +b.id, isAsc); 74 | default: return 0; 75 | } 76 | }); 77 | } 78 | } 79 | 80 | /** Simple sort comparator for example ID/Name columns (for client-side sorting). */ 81 | function compare(a: string | number, b: string | number, isAsc: boolean): number { 82 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 83 | } 84 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/watcher-list/watcher-list.component.css: -------------------------------------------------------------------------------- 1 | .full-width-table { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/watcher-list/watcher-list.component.html: -------------------------------------------------------------------------------- 1 |

Watchers

2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
Id{{row.id}}Name{{row.name}}
20 | 21 | 27 | 28 |
29 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/components/watcher-list/watcher-list.component.ts: -------------------------------------------------------------------------------- 1 | import { AfterViewInit, Component, ViewChild } from '@angular/core'; 2 | import { MatPaginator } from '@angular/material/paginator'; 3 | import { MatSort } from '@angular/material/sort'; 4 | import { MatTable } from '@angular/material/table'; 5 | import { PanelClientService, WatcherItemModel } from 'src/app/services/panel-client.service'; 6 | import { WatcherListDataSource } from './watcher-list-datasource'; 7 | 8 | @Component({ 9 | selector: 'app-watcher-list', 10 | templateUrl: './watcher-list.component.html', 11 | styleUrls: ['./watcher-list.component.css'] 12 | }) 13 | export class WatcherListComponent implements AfterViewInit { 14 | @ViewChild(MatPaginator) paginator!: MatPaginator; 15 | @ViewChild(MatSort) sort!: MatSort; 16 | @ViewChild(MatTable) table!: MatTable; 17 | dataSource!: WatcherListDataSource; 18 | 19 | displayedColumns = ['id', 'name']; 20 | 21 | constructor(private panelClient: PanelClientService) { 22 | } 23 | 24 | ngAfterViewInit(): void { 25 | this.panelClient.getWatchers().subscribe(result => { 26 | this.dataSource = new WatcherListDataSource(result.model); 27 | this.dataSource.sort = this.sort; 28 | this.dataSource.paginator = this.paginator; 29 | this.table.dataSource = this.dataSource; 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/services/common.ts: -------------------------------------------------------------------------------- 1 | export class Response { 2 | } 3 | 4 | export class ListResponse extends Response { 5 | public model!: TModel[]; 6 | } 7 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/services/monitor-client.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { MONITOR_API_ENDPOINT } from 'src/settings'; 5 | import { ListResponse } from './common'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class MonitorClientService { 11 | 12 | private endpoint: string; 13 | 14 | constructor(private http: HttpClient) { 15 | this.endpoint = `${MONITOR_API_ENDPOINT}/api/v1`; 16 | } 17 | 18 | public getMonitor(): Observable> { 19 | const url = `${this.endpoint}/monitor`; 20 | return this.http.get>(url); 21 | } 22 | } 23 | 24 | export class ResourceWatchItemModel { 25 | public id!: number; 26 | public resourceId!: number; 27 | public resource!: string; 28 | public resourceCategoryId!: number; 29 | public resourceCategory!: string; 30 | public environmentId!: number; 31 | public environment!: string; 32 | public successful!: boolean; 33 | public watchCount!: number; 34 | public lastWatch!: Date; 35 | public interval!: number; 36 | } 37 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/app/services/panel-client.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | import { PANEL_API_ENDPOINT } from 'src/settings'; 5 | import { ListResponse } from './common'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class PanelClientService { 11 | 12 | private readonly endpoint: string; 13 | 14 | constructor(private http: HttpClient) { 15 | this.endpoint = `${PANEL_API_ENDPOINT}/api/v1`; 16 | } 17 | 18 | public getWatchers(): Observable> { 19 | const url = `${this.endpoint}/watcher`; 20 | return this.http.get>(url); 21 | } 22 | 23 | public getResources(): Observable> { 24 | const url = `${this.endpoint}/resource`; 25 | return this.http.get>(url); 26 | } 27 | } 28 | 29 | export class WatcherItemModel { 30 | public id!: number; 31 | public name!: string; 32 | public description!: string; 33 | public className!: string; 34 | } 35 | 36 | export class ResourceItemModel { 37 | public id!: number; 38 | public name!: string; 39 | public resourceCategoryId!: number; 40 | public resourceCategory!: string; 41 | } 42 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hherzl/TheWatcher/e69caa503e8063f7dc54134a38278de8be95e32d/Source/Frontend/thewatcher-gui/src/assets/.gitkeep -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hherzl/TheWatcher/e69caa503e8063f7dc54134a38278de8be95e32d/Source/Frontend/thewatcher-gui/src/favicon.ico -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The Watcher 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/settings.ts: -------------------------------------------------------------------------------- 1 | export const MONITOR_API_ENDPOINT: string = 'https://localhost:13002'; 2 | export const PANEL_API_ENDPOINT: string = 'https://localhost:13003'; 3 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | // First, initialize the Angular testing environment. 11 | getTestBed().initTestEnvironment( 12 | BrowserDynamicTestingModule, 13 | platformBrowserDynamicTesting(), 14 | ); 15 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2020", 23 | "dom" 24 | ], 25 | "useDefineForClassFields": false 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Source/Frontend/thewatcher-gui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | --------------------------------------------------------------------------------