pve connector startup

master
Tudor Stanciu 2022-03-02 09:40:51 +02:00
parent 603eeb8783
commit 8b6aa4878c
18 changed files with 283 additions and 108 deletions

View File

@ -8,6 +8,7 @@
<SerilogSinksSQLitePackageVersion>5.0.0</SerilogSinksSQLitePackageVersion> <SerilogSinksSQLitePackageVersion>5.0.0</SerilogSinksSQLitePackageVersion>
<NDBExtensionsSwaggerPackageVersion>1.0.2</NDBExtensionsSwaggerPackageVersion> <NDBExtensionsSwaggerPackageVersion>1.0.2</NDBExtensionsSwaggerPackageVersion>
<NDBSecurityAuthenticationIdentityPackageVersion>1.0.7</NDBSecurityAuthenticationIdentityPackageVersion> <NDBSecurityAuthenticationIdentityPackageVersion>1.0.7</NDBSecurityAuthenticationIdentityPackageVersion>
<NDBDatabaseMigrationPackageVersion>1.1.3</NDBDatabaseMigrationPackageVersion>
<AutoMapperPackageVersion>10.1.1</AutoMapperPackageVersion> <AutoMapperPackageVersion>10.1.1</AutoMapperPackageVersion>
<ScrutorPackageVersion>3.3.0</ScrutorPackageVersion> <ScrutorPackageVersion>3.3.0</ScrutorPackageVersion>
<MicrosoftAspNetCorePackageVersion>5.0.7</MicrosoftAspNetCorePackageVersion> <MicrosoftAspNetCorePackageVersion>5.0.7</MicrosoftAspNetCorePackageVersion>

View File

@ -1,6 +1,10 @@
namespace ProxmoxConnector.Integration.Abstractions using System.Threading.Tasks;
namespace ProxmoxConnector.Integration.Abstractions
{ {
public interface IPveConnector public interface IPveConnector
{ {
Task TestWithLogin();
Task TestWithToken();
} }
} }

View File

@ -8,10 +8,10 @@ namespace ProxmoxConnector.Integration.Corsinvest.Services
{ {
internal class PveConnector : IPveConnector internal class PveConnector : IPveConnector
{ {
public async Task Test() public async Task TestWithLogin()
{ {
var client = new PveClient("***REMOVED***"); ***REMOVED*** var client = new PveClient("***REMOVED***"); ***REMOVED***
if (await client.Login("root", "password")) if (await client.Login(***REMOVED***))
{ {
var vm = client.Nodes["pve1"].Qemu[100]; var vm = client.Nodes["pve1"].Qemu[100];
@ -40,7 +40,10 @@ namespace ProxmoxConnector.Integration.Corsinvest.Services
var dataImg = (await client.Nodes["pve1"].Rrd.Rrd("cpu", "day")).Response; var dataImg = (await client.Nodes["pve1"].Rrd.Rrd("cpu", "day")).Response;
Console.WriteLine("<img src=\"{dataImg}\" \\>"); Console.WriteLine("<img src=\"{dataImg}\" \\>");
} }
}
public async Task TestWithToken()
{
//using Api Token //using Api Token
var client2 = new PveClient("10.92.100.33"); var client2 = new PveClient("10.92.100.33");
client2.ApiToken = "root@pam!qqqqqq=***REMOVED***"; client2.ApiToken = "root@pam!qqqqqq=***REMOVED***";

View File

@ -1,8 +0,0 @@
using System;
namespace ProxmoxConnector.Server.Application
{
public class Class1
{
}
}

View File

@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using ProxmoxConnector.Integration.Corsinvest;
using System;
namespace ProxmoxConnector.Server.Application
{
public static class DependencyInjectionExtensions
{
public static void AddApplicationServices(this IServiceCollection services)
{
services.AddCorsinvestPveConnector();
}
}
}

View File

@ -0,0 +1,12 @@
using AutoMapper;
namespace ProxmoxConnector.Server.Application.Mappings
{
public class MappingProfile : Profile
{
public MappingProfile()
{
//CreateMap<models.Token, dto.Token>();
}
}
}

View File

@ -12,5 +12,10 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
<PackageReference Include="Scrutor" Version="$(ScrutorPackageVersion)" /> <PackageReference Include="Scrutor" Version="$(ScrutorPackageVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\integration\ProxmoxConnector.Integration.Corsinvest\ProxmoxConnector.Integration.Corsinvest.csproj" />
<ProjectReference Include="..\ProxmoxConnector.Server.Domain\ProxmoxConnector.Server.Domain.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Data.Common;
using System.IO;
namespace ProxmoxConnector.Server.Application.Services.Environment
{
public class EnvironmentConfigurator
{
private readonly string _workspace;
private readonly string _databaseConnection;
public EnvironmentConfigurator(IConfigurationRoot configuration)
{
_workspace = configuration.GetValue<string>("Workspace");
_databaseConnection = configuration.GetConnectionString("DatabaseConnection");
}
public void Configure()
{
if (string.IsNullOrEmpty(_workspace))
throw new Exception($"Workspace path is empty! Check 'Workspace' parameter.");
if (!Directory.Exists(_workspace))
Directory.CreateDirectory(_workspace);
}
public (string databasePath, string workspace) GetStorageTools()
{
var builder = new DbConnectionStringBuilder
{
ConnectionString = _databaseConnection
};
var dataSource = builder["Data Source"].ToString();
var databasePath = dataSource.Replace("{Workspace}", _workspace);
return (databasePath, _workspace);
}
}
}

View File

@ -0,0 +1,10 @@
namespace ProxmoxConnector.Server.Domain.Abstractions
{
public interface IUserService
{
bool UserIsLoggedIn { get; }
string GetUserId();
string GetUserName();
bool UserIsGuest();
}
}

View File

@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
namespace ProxmoxConnector.Server.Controllers
{
[Authorize]
[ApiController]
[Route("health")]
public class HealthController : ControllerBase
{
private readonly ILogger<HealthController> _logger;
public HealthController(ILogger<HealthController> logger)
{
_logger = logger;
}
[AllowAnonymous]
[HttpGet("ping")]
public IActionResult Ping()
{
_logger.LogInformation("Ping");
return Ok($"System datetime: {DateTime.Now}");
}
}
}

View File

@ -1,39 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ProxmoxConnector.Server.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using ProxmoxConnector.Server.Application.Services.Environment;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System; using System;
using System.Collections.Generic; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace ProxmoxConnector.Server namespace ProxmoxConnector.Server
{ {
@ -13,14 +16,69 @@ namespace ProxmoxConnector.Server
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
CreateHostBuilder(args).Build().Run(); var isContainer = args.Contains("--docker");
if (!isContainer)
{
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
}
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var configurator = new EnvironmentConfigurator(configuration);
configurator.Configure();
var (databasePath, workspace) = configurator.GetStorageTools();
var loggingLevelParam = configuration.GetValue<string>("Logging:LogLevel:Default");
if (!Enum.TryParse(loggingLevelParam, out LogEventLevel loggingLevel))
throw new Exception($"Unknown logging level '{loggingLevelParam}'.");
var loggingLevelSwitch = new LoggingLevelSwitch(loggingLevel);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(loggingLevelSwitch)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.SQLite(databasePath, "__Logs", levelSwitch: loggingLevelSwitch)
.CreateLogger();
try
{
var urls = configuration.GetValue<string>("urls");
Log.Information("Starting Proxmox connector...");
Log.Information($"API listening on {urls}");
Log.Information($"Workspace configured at '{workspace}' path");
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
CreateHostBuilder(args, configuration).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "CDN Server host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
} }
public static IHostBuilder CreateHostBuilder(string[] args) => public static IHostBuilder CreateHostBuilder(string[] args, IConfiguration configuration)
Host.CreateDefaultBuilder(args) {
var builder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>
{ {
webBuilder.UseStartup<Startup>(); webBuilder.UseStartup<Startup>()
.UseConfiguration(configuration)
.UseSerilog();
}); });
return builder;
}
} }
} }

View File

@ -1,22 +1,6 @@
{ {
"$schema": "http://json.schemastore.org/launchsettings.json", "$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:65222",
"sslPort": 0
}
},
"profiles": { "profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ProxmoxConnector.Server": { "ProxmoxConnector.Server": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": "true", "dotnetRunMessages": "true",

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
@ -8,9 +8,15 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="$(AutoMapperExtensionsPackageVersion)" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="$(AutoMapperExtensionsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(NewtonsoftJsonPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(NewtonsoftJsonPackageVersion)" />
<PackageReference Include="NDB.Extensions.Swagger" Version="$(NDBExtensionsSwaggerPackageVersion)" /> <PackageReference Include="NDB.Extensions.Swagger" Version="$(NDBExtensionsSwaggerPackageVersion)" />
<PackageReference Include="NDB.Infrastructure.DatabaseMigration" Version="$(NDBDatabaseMigrationPackageVersion)" />
<PackageReference Include="NDB.Security.Authentication.Identity" Version="$(NDBSecurityAuthenticationIdentityPackageVersion)" /> <PackageReference Include="NDB.Security.Authentication.Identity" Version="$(NDBSecurityAuthenticationIdentityPackageVersion)" />
<PackageReference Include="Serilog.AspNetCore" Version="$(SerilogAspNetCorePackageVersion)" /> <PackageReference Include="Serilog.AspNetCore" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageReference Include="Serilog.Sinks.SQLite" Version="$(SerilogSinksSQLitePackageVersion)" /> <PackageReference Include="Serilog.Sinks.SQLite" Version="$(SerilogSinksSQLitePackageVersion)" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProxmoxConnector.Server.Application\ProxmoxConnector.Server.Application.csproj" />
<ProjectReference Include="..\ProxmoxConnector.Server.Domain.Data\ProxmoxConnector.Server.Domain.Data.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,46 @@
using Microsoft.AspNetCore.Http;
using ProxmoxConnector.Server.Domain.Abstractions;
using System;
using System.Linq;
using System.Security.Claims;
namespace ProxmoxConnector.Server.Services
{
public class UserService : IUserService
{
private readonly IHttpContextAccessor _httpAccessor;
public UserService(IHttpContextAccessor httpAccessor)
{
_httpAccessor = httpAccessor;
}
public bool UserIsLoggedIn => _httpAccessor.HttpContext.User != null;
public string GetUserId()
{
var userId = _httpAccessor.HttpContext.User?.Claims.FirstOrDefault(z => z.Type == ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
throw new Exception("User id could not be retrieved from claims.");
return userId;
}
public string GetUserName()
{
var userName = _httpAccessor.HttpContext.User?.Claims.FirstOrDefault(z => z.Type == ClaimTypes.Name)?.Value;
if (string.IsNullOrEmpty(userName))
throw new Exception("User name could not be retrieved from claims.");
return userName;
}
public bool UserIsGuest()
{
var userIsGuest = _httpAccessor.HttpContext.User?.Claims.FirstOrDefault(z => z.Type == NDB.Security.Authentication.Identity.Constants.ClaimTypes.IsGuestUser)?.Value;
return !string.IsNullOrEmpty(userIsGuest) && bool.TrueString == userIsGuest;
}
}
}

View File

@ -6,6 +6,14 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using NDB.Extensions.Swagger;
using NDB.Extensions.Swagger.Constants;
using NDB.Infrastructure.DatabaseMigration;
using NDB.Security.Authentication.Identity;
using Newtonsoft.Json;
using ProxmoxConnector.Server.Application;
using ProxmoxConnector.Server.Domain.Abstractions;
using ProxmoxConnector.Server.Services;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -15,42 +23,51 @@ namespace ProxmoxConnector.Server
{ {
public class Startup public class Startup
{ {
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; _configuration = configuration;
} }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddControllers().AddNewtonsoftJson(o => o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc);
services.AddControllers(); // Add basic authentication
services.AddSwaggerGen(c => services.AddIdentityAuthentication(_configuration.GetSection("IdentityServer")["BaseAddress"]);
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "ProxmoxConnector.Server", Version = "v1" }); services.AddHttpContextAccessor();
}); services.AddScoped<IUserService, UserService>();
services.AddSwagger("ProxmoxConnector.Server", AuthorizationType.InhouseIdentity);
services.AddAutoMapper(typeof(Application.Mappings.MappingProfile).Assembly);
var workspace = _configuration.GetValue<string>("Workspace");
services.AddMigration(workspace: workspace);
//services.AddDataAccess();
services.AddApplicationServices();
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ {
if (env.IsDevelopment()) app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
{ app.UseExceptionHandler("/error");
app.UseDeveloperExceptionPage();
app.UseSwagger(); app.ConfigureSwagger("CDN.Server v1");
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ProxmoxConnector.Server v1"));
}
app.UseRouting(); app.UseRouting();
app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {
endpoints.MapControllers(); endpoints.MapControllers();
}); });
app.UseMigration();
} }
} }
} }

View File

@ -1,15 +0,0 @@
using System;
namespace ProxmoxConnector.Server
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}

View File

@ -1,10 +1,19 @@
{ {
"urls": "http://*:7000",
"ConnectionStrings": {
"DatabaseConnection": "Data Source={Workspace}\\ProxmoxConnector.db"
},
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Debug",
"Microsoft": "Warning", "Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
} "IdentityServer": {
//"BaseAddress": "http://localhost:5063/"
"BaseAddress": "https://toodle.ddns.net/identity-server-api/"
},
"Workspace": "Workspace"
}