diff --git a/dependencies.props b/dependencies.props
index e67b266..11b84d3 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -8,6 +8,7 @@
5.0.0
1.0.2
1.0.7
+ 1.1.3
10.1.1
3.3.0
5.0.7
diff --git a/src/integration/ProxmoxConnector.Integration.Abstractions/IPveConnector.cs b/src/integration/ProxmoxConnector.Integration.Abstractions/IPveConnector.cs
index 0f11bff..ec2f48f 100644
--- a/src/integration/ProxmoxConnector.Integration.Abstractions/IPveConnector.cs
+++ b/src/integration/ProxmoxConnector.Integration.Abstractions/IPveConnector.cs
@@ -1,6 +1,10 @@
-namespace ProxmoxConnector.Integration.Abstractions
+using System.Threading.Tasks;
+
+namespace ProxmoxConnector.Integration.Abstractions
{
public interface IPveConnector
{
+ Task TestWithLogin();
+ Task TestWithToken();
}
}
diff --git a/src/integration/ProxmoxConnector.Integration.Corsinvest/Services/PveConnector.cs b/src/integration/ProxmoxConnector.Integration.Corsinvest/Services/PveConnector.cs
index 740b2ab..5672ce5 100644
--- a/src/integration/ProxmoxConnector.Integration.Corsinvest/Services/PveConnector.cs
+++ b/src/integration/ProxmoxConnector.Integration.Corsinvest/Services/PveConnector.cs
@@ -8,10 +8,10 @@ namespace ProxmoxConnector.Integration.Corsinvest.Services
{
internal class PveConnector : IPveConnector
{
- public async Task Test()
+ public async Task TestWithLogin()
{
var client = new PveClient("***REMOVED***"); ***REMOVED***
- if (await client.Login("root", "password"))
+ if (await client.Login(***REMOVED***))
{
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;
Console.WriteLine("");
}
+ }
+ public async Task TestWithToken()
+ {
//using Api Token
var client2 = new PveClient("10.92.100.33");
client2.ApiToken = "root@pam!qqqqqq=***REMOVED***";
diff --git a/src/server/ProxmoxConnector.Server.Application/Class1.cs b/src/server/ProxmoxConnector.Server.Application/Class1.cs
deleted file mode 100644
index e066fea..0000000
--- a/src/server/ProxmoxConnector.Server.Application/Class1.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System;
-
-namespace ProxmoxConnector.Server.Application
-{
- public class Class1
- {
- }
-}
diff --git a/src/server/ProxmoxConnector.Server.Application/DependencyInjectionExtensions.cs b/src/server/ProxmoxConnector.Server.Application/DependencyInjectionExtensions.cs
new file mode 100644
index 0000000..dcc5a9b
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server.Application/DependencyInjectionExtensions.cs
@@ -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();
+ }
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server.Application/Mappings/MappingProfile.cs b/src/server/ProxmoxConnector.Server.Application/Mappings/MappingProfile.cs
new file mode 100644
index 0000000..1ee4bc1
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server.Application/Mappings/MappingProfile.cs
@@ -0,0 +1,12 @@
+using AutoMapper;
+
+namespace ProxmoxConnector.Server.Application.Mappings
+{
+ public class MappingProfile : Profile
+ {
+ public MappingProfile()
+ {
+ //CreateMap();
+ }
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server.Application/ProxmoxConnector.Server.Application.csproj b/src/server/ProxmoxConnector.Server.Application/ProxmoxConnector.Server.Application.csproj
index 0825fe9..ce8567b 100644
--- a/src/server/ProxmoxConnector.Server.Application/ProxmoxConnector.Server.Application.csproj
+++ b/src/server/ProxmoxConnector.Server.Application/ProxmoxConnector.Server.Application.csproj
@@ -12,5 +12,10 @@
+
+
+
+
+
diff --git a/src/server/ProxmoxConnector.Server.Application/Services/Environment/EnvironmentConfigurator.cs b/src/server/ProxmoxConnector.Server.Application/Services/Environment/EnvironmentConfigurator.cs
new file mode 100644
index 0000000..16821fa
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server.Application/Services/Environment/EnvironmentConfigurator.cs
@@ -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("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);
+ }
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server.Domain/Abstractions/IUserService.cs b/src/server/ProxmoxConnector.Server.Domain/Abstractions/IUserService.cs
new file mode 100644
index 0000000..10c6996
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server.Domain/Abstractions/IUserService.cs
@@ -0,0 +1,10 @@
+namespace ProxmoxConnector.Server.Domain.Abstractions
+{
+ public interface IUserService
+ {
+ bool UserIsLoggedIn { get; }
+ string GetUserId();
+ string GetUserName();
+ bool UserIsGuest();
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server/Controllers/HealthController.cs b/src/server/ProxmoxConnector.Server/Controllers/HealthController.cs
new file mode 100644
index 0000000..50d03b5
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server/Controllers/HealthController.cs
@@ -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 _logger;
+
+ public HealthController(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ [AllowAnonymous]
+ [HttpGet("ping")]
+ public IActionResult Ping()
+ {
+ _logger.LogInformation("Ping");
+ return Ok($"System datetime: {DateTime.Now}");
+ }
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server/Controllers/WeatherForecastController.cs b/src/server/ProxmoxConnector.Server/Controllers/WeatherForecastController.cs
deleted file mode 100644
index 26f1eb5..0000000
--- a/src/server/ProxmoxConnector.Server/Controllers/WeatherForecastController.cs
+++ /dev/null
@@ -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 _logger;
-
- public WeatherForecastController(ILogger logger)
- {
- _logger = logger;
- }
-
- [HttpGet]
- public IEnumerable 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();
- }
- }
-}
diff --git a/src/server/ProxmoxConnector.Server/Program.cs b/src/server/ProxmoxConnector.Server/Program.cs
index d71492b..7ffa91d 100644
--- a/src/server/ProxmoxConnector.Server/Program.cs
+++ b/src/server/ProxmoxConnector.Server/Program.cs
@@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
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.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
-using System.Threading.Tasks;
namespace ProxmoxConnector.Server
{
@@ -13,14 +16,69 @@ namespace ProxmoxConnector.Server
{
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("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("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) =>
- Host.CreateDefaultBuilder(args)
+ public static IHostBuilder CreateHostBuilder(string[] args, IConfiguration configuration)
+ {
+ var builder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
- webBuilder.UseStartup();
+ webBuilder.UseStartup()
+ .UseConfiguration(configuration)
+ .UseSerilog();
});
+
+ return builder;
+ }
}
}
diff --git a/src/server/ProxmoxConnector.Server/Properties/launchSettings.json b/src/server/ProxmoxConnector.Server/Properties/launchSettings.json
index 2536590..99303cb 100644
--- a/src/server/ProxmoxConnector.Server/Properties/launchSettings.json
+++ b/src/server/ProxmoxConnector.Server/Properties/launchSettings.json
@@ -1,22 +1,6 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "http://localhost:65222",
- "sslPort": 0
- }
- },
"profiles": {
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "launchUrl": "swagger",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- },
"ProxmoxConnector.Server": {
"commandName": "Project",
"dotnetRunMessages": "true",
diff --git a/src/server/ProxmoxConnector.Server/ProxmoxConnector.Server.csproj b/src/server/ProxmoxConnector.Server/ProxmoxConnector.Server.csproj
index d870710..cd94eb2 100644
--- a/src/server/ProxmoxConnector.Server/ProxmoxConnector.Server.csproj
+++ b/src/server/ProxmoxConnector.Server/ProxmoxConnector.Server.csproj
@@ -1,4 +1,4 @@
-
+
net5.0
@@ -8,9 +8,15 @@
+
+
+
+
+
+
diff --git a/src/server/ProxmoxConnector.Server/Services/UserService.cs b/src/server/ProxmoxConnector.Server/Services/UserService.cs
new file mode 100644
index 0000000..c9644e8
--- /dev/null
+++ b/src/server/ProxmoxConnector.Server/Services/UserService.cs
@@ -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;
+ }
+ }
+}
diff --git a/src/server/ProxmoxConnector.Server/Startup.cs b/src/server/ProxmoxConnector.Server/Startup.cs
index 6f41cb5..40297b5 100644
--- a/src/server/ProxmoxConnector.Server/Startup.cs
+++ b/src/server/ProxmoxConnector.Server/Startup.cs
@@ -6,6 +6,14 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
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.Collections.Generic;
using System.Linq;
@@ -15,42 +23,51 @@ namespace ProxmoxConnector.Server
{
public class Startup
{
+ private readonly 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.
public void ConfigureServices(IServiceCollection services)
{
+ services.AddControllers().AddNewtonsoftJson(o => o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc);
- services.AddControllers();
- services.AddSwaggerGen(c =>
- {
- c.SwaggerDoc("v1", new OpenApiInfo { Title = "ProxmoxConnector.Server", Version = "v1" });
- });
+ // Add basic authentication
+ services.AddIdentityAuthentication(_configuration.GetSection("IdentityServer")["BaseAddress"]);
+
+ services.AddHttpContextAccessor();
+ services.AddScoped();
+ services.AddSwagger("ProxmoxConnector.Server", AuthorizationType.InhouseIdentity);
+
+ services.AddAutoMapper(typeof(Application.Mappings.MappingProfile).Assembly);
+
+ var workspace = _configuration.GetValue("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.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseSwagger();
- app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ProxmoxConnector.Server v1"));
- }
+ app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
+ app.UseExceptionHandler("/error");
+
+ app.ConfigureSwagger("CDN.Server v1");
app.UseRouting();
-
+ app.UseAuthentication();
app.UseAuthorization();
-
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
+
+ app.UseMigration();
}
}
}
diff --git a/src/server/ProxmoxConnector.Server/WeatherForecast.cs b/src/server/ProxmoxConnector.Server/WeatherForecast.cs
deleted file mode 100644
index 5e35eed..0000000
--- a/src/server/ProxmoxConnector.Server/WeatherForecast.cs
+++ /dev/null
@@ -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; }
- }
-}
diff --git a/src/server/ProxmoxConnector.Server/appsettings.json b/src/server/ProxmoxConnector.Server/appsettings.json
index d9d9a9b..cb8e87e 100644
--- a/src/server/ProxmoxConnector.Server/appsettings.json
+++ b/src/server/ProxmoxConnector.Server/appsettings.json
@@ -1,10 +1,19 @@
{
+ "urls": "http://*:7000",
+ "ConnectionStrings": {
+ "DatabaseConnection": "Data Source={Workspace}\\ProxmoxConnector.db"
+ },
"Logging": {
"LogLevel": {
- "Default": "Information",
+ "Default": "Debug",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
- "AllowedHosts": "*"
-}
+ "AllowedHosts": "*",
+ "IdentityServer": {
+ //"BaseAddress": "http://localhost:5063/"
+ "BaseAddress": "https://toodle.ddns.net/identity-server-api/"
+ },
+ "Workspace": "Workspace"
+}
\ No newline at end of file