Merge pull request #35 from Moonlight-Panel/main

Update to upstream branch
This commit is contained in:
Marcel Baumgartner
2023-04-04 16:32:45 +02:00
committed by GitHub
24 changed files with 1045 additions and 174 deletions

View File

@@ -29,8 +29,11 @@ public class CacheLogger : ILogger
}
}
public void Info(string s)
public void Info(string? s)
{
if (s == null)
return;
lock (Messages)
{
Messages.Add(new()
@@ -39,12 +42,15 @@ public class CacheLogger : ILogger
Message = s
});
}
SbLogger.Info(s);
}
public void Debug(string s)
public void Debug(string? s)
{
if (s == null)
return;
lock (Messages)
{
Messages.Add(new()
@@ -53,12 +59,15 @@ public class CacheLogger : ILogger
Message = s
});
}
SbLogger.Debug(s);
}
public void Warn(string s)
public void Warn(string? s)
{
if (s == null)
return;
lock (Messages)
{
Messages.Add(new()
@@ -67,12 +76,15 @@ public class CacheLogger : ILogger
Message = s
});
}
SbLogger.Warn(s);
}
public void Error(string s)
public void Error(string? s)
{
if (s == null)
return;
lock (Messages)
{
Messages.Add(new()
@@ -81,12 +93,15 @@ public class CacheLogger : ILogger
Message = s
});
}
SbLogger.Error(s);
}
public void Fatal(string s)
public void Fatal(string? s)
{
if (s == null)
return;
lock (Messages)
{
Messages.Add(new()
@@ -95,7 +110,7 @@ public class CacheLogger : ILogger
Message = s
});
}
SbLogger.Fatal(s);
}
@@ -109,7 +124,7 @@ public class CacheLogger : ILogger
Message = ex.ToStringDemystified()
});
}
SbLogger.InfoEx(ex);
}
@@ -123,7 +138,7 @@ public class CacheLogger : ILogger
Message = ex.ToStringDemystified()
});
}
SbLogger.DebugEx(ex);
}
@@ -137,7 +152,7 @@ public class CacheLogger : ILogger
Message = ex.ToStringDemystified()
});
}
SbLogger.WarnEx(ex);
}
@@ -151,7 +166,7 @@ public class CacheLogger : ILogger
Message = ex.ToStringDemystified()
});
}
SbLogger.ErrorEx(ex);
}
@@ -165,7 +180,7 @@ public class CacheLogger : ILogger
Message = ex.ToStringDemystified()
});
}
SbLogger.FatalEx(ex);
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Models.Forms;
public class ServerOrderDataModel
{
[Required(ErrorMessage = "You need to enter a name")]
[MaxLength(32, ErrorMessage = "The name cannot be longer that 32 characters")]
public string Name { get; set; } = "";
[Required(ErrorMessage = "You need to specify a server image")]
public Image Image { get; set; }
}

View File

@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms;
public class ServerRenameDataModel
{
[Required(ErrorMessage = "You need to enter a name")]
[MaxLength(32, ErrorMessage = "The name cannot be longer that 32 characters")]
public string Name { get; set; }
}

View File

@@ -5,6 +5,12 @@ public class SubscriptionLimit
public string Identifier { get; set; } = "";
public int Amount { get; set; }
public List<LimitOption> Options { get; set; } = new();
public string? ReadValue(string key)
{
var d = Options.FirstOrDefault(x => string.Equals(x.Key, key, StringComparison.InvariantCultureIgnoreCase));
return d?.Value;
}
public class LimitOption
{

View File

@@ -5,10 +5,12 @@ namespace Moonlight.App.Services.Interop;
public class AlertService
{
private readonly SweetAlertService SweetAlertService;
private readonly SmartTranslateService SmartTranslateService;
public AlertService(SweetAlertService service)
public AlertService(SweetAlertService service, SmartTranslateService smartTranslateService)
{
SweetAlertService = service;
SmartTranslateService = smartTranslateService;
}
public async Task Info(string title, string desciption)
@@ -21,6 +23,11 @@ public class AlertService
});
}
public async Task Info(string desciption)
{
await Info("", desciption);
}
public async Task Success(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
@@ -31,6 +38,11 @@ public class AlertService
});
}
public async Task Success(string desciption)
{
await Success("", desciption);
}
public async Task Warning(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
@@ -41,6 +53,11 @@ public class AlertService
});
}
public async Task Warning(string desciption)
{
await Warning("", desciption);
}
public async Task Error(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
@@ -51,6 +68,11 @@ public class AlertService
});
}
public async Task Error(string desciption)
{
await Error("", desciption);
}
public async Task<bool> YesNo(string title, string desciption, string yesText, string noText)
{
var result = await SweetAlertService.FireAsync(new SweetAlertOptions()
@@ -79,4 +101,27 @@ public class AlertService
return result.Value;
}
public async Task<bool> ConfirmMath()
{
var r = new Random();
var i1 = r.Next(5, 15);
var i2 = r.Next(5, 15);
var input = await Text(
SmartTranslateService.Translate("Confirm"),
$"{i1} + {i2} =",
""
);
if (int.TryParse(input, out int i))
{
if (i == i1 + i2)
{
return true;
}
}
return false;
}
}

View File

@@ -15,4 +15,9 @@ public class ClipboardService
{
await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data);
}
public async Task Copy(string data)
{
await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data);
}
}

View File

@@ -1,11 +1,9 @@
using Logging.Net;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database;
using Moonlight.App.Database.Entities;
using Moonlight.App.Exceptions;
using Moonlight.App.Helpers;
using Moonlight.App.Models.Files;
using Moonlight.App.Models.Files.Accesses;
using Moonlight.App.Helpers.Files;
using Moonlight.App.Models.Misc;
using Moonlight.App.Models.Wings;
using Moonlight.App.Models.Wings.Requests;
@@ -13,6 +11,7 @@ using Moonlight.App.Models.Wings.Resources;
using Moonlight.App.Repositories;
using Moonlight.App.Repositories.Servers;
using Moonlight.App.Services.LogServices;
using FileAccess = Moonlight.App.Helpers.Files.FileAccess;
namespace Moonlight.App.Services;
@@ -30,7 +29,6 @@ public class ServerService
private readonly SecurityLogService SecurityLogService;
private readonly AuditLogService AuditLogService;
private readonly ErrorLogService ErrorLogService;
private readonly string AppUrl;
public ServerService(
ServerRepository serverRepository,
@@ -58,8 +56,6 @@ public class ServerService
SecurityLogService = securityLogService;
AuditLogService = auditLogService;
ErrorLogService = errorLogService;
AppUrl = ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl");
}
private Server EnsureNodeData(Server s)
@@ -225,17 +221,17 @@ public class ServerService
return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}";
}
public Task<IFileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url
public Task<FileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url
{
Server server = EnsureNodeData(s);
return Task.FromResult(
(IFileAccess)new WingsFileAccess(
(FileAccess)new WingsFileAccess(
WingsApiHelper,
server,
user,
WingsJwtHelper,
AppUrl
server,
ConfigService,
user
)
);
}
@@ -383,4 +379,20 @@ public class ServerService
throw new Exception("User and owner id do not match");
}
}
public async Task Sync(Server s)
{
var server = EnsureNodeData(s);
await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/sync", null);
}
public async Task Delete(Server s)
{
var server = EnsureNodeData(s);
await WingsApiHelper.Delete(server.Node, $"api/servers/{server.Uuid}", null);
ServerRepository.Delete(s);
}
}

View File

@@ -0,0 +1,64 @@
using Moonlight.App.Database.Entities;
using Moonlight.App.Repositories;
namespace Moonlight.App.Services;
public class SmartDeployService
{
private readonly NodeRepository NodeRepository;
private readonly NodeService NodeService;
public SmartDeployService(NodeRepository nodeRepository, NodeService nodeService)
{
NodeRepository = nodeRepository;
NodeService = nodeService;
}
public async Task<Node?> GetNode()
{
var data = new Dictionary<Node, double>();
foreach (var node in NodeRepository.Get().ToArray())
{
var u = await GetUsageScore(node);
if(u != 0)
data.Add(node, u);
}
if (!data.Any())
return null;
return data.MaxBy(x => x.Value).Key;
}
private async Task<double> GetUsageScore(Node node)
{
var score = 0;
try
{
var cpuStats = await NodeService.GetCpuStats(node);
var memoryStats = await NodeService.GetMemoryStats(node);
var diskStats = await NodeService.GetDiskStats(node);
var cpuWeight = 0.5; // Weight of CPU usage in the final score
var memoryWeight = 0.3; // Weight of memory usage in the final score
var diskSpaceWeight = 0.2; // Weight of free disk space in the final score
var cpuScore = (1 - cpuStats.Usage) * cpuWeight; // CPU score is based on the inverse of CPU usage
var memoryScore = (1 - (memoryStats.Used / 1024)) * memoryWeight; // Memory score is based on the percentage of free memory
var diskSpaceScore = (double) diskStats.FreeBytes / 1000000000 * diskSpaceWeight; // Disk space score is based on the amount of free disk space in GB
var finalScore = cpuScore + memoryScore + diskSpaceScore;
return finalScore;
}
catch (Exception e)
{
// ignored
}
return score;
}
}

View File

@@ -78,49 +78,45 @@ public class SubscriptionService
await OneTimeJwtService.Revoke(code);
}
public async Task Cancel()
{
if (await GetCurrent() != null)
{
var user = await GetCurrentUser();
user.CurrentSubscription = null;
UserRepository.Update(user);
}
}
public async Task<SubscriptionLimit> GetLimit(string identifier)
{
var configSection = ConfigService.GetSection("Moonlight").GetSection("Subscriptions");
var defaultLimits = configSection.GetValue<SubscriptionLimit[]>("defaultLimits");
var subscription = await GetCurrent();
if (subscription == null)
{
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
if (foundDefault != null)
return foundDefault;
return new()
{
Identifier = identifier,
Amount = 0
};
}
else
var subscriptionLimits =
JsonConvert.DeserializeObject<SubscriptionLimit[]>(subscription.LimitsJson)
?? Array.Empty<SubscriptionLimit>();
var foundLimit = subscriptionLimits.FirstOrDefault(x => x.Identifier == identifier);
if (foundLimit != null)
return foundLimit;
return new()
{
var subscriptionLimits =
JsonConvert.DeserializeObject<SubscriptionLimit[]>(subscription.LimitsJson)
?? Array.Empty<SubscriptionLimit>();
var foundLimit = subscriptionLimits.FirstOrDefault(x => x.Identifier == identifier);
if (foundLimit != null)
return foundLimit;
var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier);
if (foundDefault != null)
return foundDefault;
return new()
{
Identifier = identifier,
Amount = 0
};
}
Identifier = identifier,
Amount = 0
};
}
private async Task<User?> GetCurrentUser()