Merge pull request #35 from Moonlight-Panel/main
Update to upstream branch
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
14
Moonlight/App/Models/Forms/ServerOrderDataModel.cs
Normal file
14
Moonlight/App/Models/Forms/ServerOrderDataModel.cs
Normal 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; }
|
||||
}
|
||||
10
Moonlight/App/Models/Forms/ServerRenameDataModel.cs
Normal file
10
Moonlight/App/Models/Forms/ServerRenameDataModel.cs
Normal 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; }
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,9 @@ public class ClipboardService
|
||||
{
|
||||
await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data);
|
||||
}
|
||||
public async Task Copy(string data)
|
||||
{
|
||||
await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
64
Moonlight/App/Services/SmartDeployService.cs
Normal file
64
Moonlight/App/Services/SmartDeployService.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user