Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11708fbc3b | ||
|
|
daeb4dd5b9 | ||
|
|
daba4cba04 | ||
|
|
1cd0f0f96f | ||
|
|
6a30db07a7 | ||
|
|
6c8754d008 | ||
|
|
356ba94592 | ||
|
|
d3b55d155b | ||
|
|
0015001d7c | ||
|
|
0a86aa8aa4 | ||
|
|
74d4ee729d | ||
|
|
178ff36e86 | ||
|
|
f852df5807 | ||
|
|
90f4b04857 | ||
|
|
244e87ed18 | ||
|
|
80ea5a543f | ||
|
|
5baba05f5f | ||
|
|
591da6de5c | ||
|
|
c1ddff4ae3 | ||
|
|
67d78d7104 | ||
|
|
52f4b00f84 | ||
|
|
8f028e2ac6 | ||
|
|
5bd6f15203 | ||
|
|
4c39ad6170 | ||
|
|
12392d4f47 | ||
|
|
b75147e4c0 | ||
|
|
8f9508f30b | ||
|
|
428e2668d3 | ||
|
|
c1cfb35c86 | ||
|
|
d6777c463e | ||
|
|
f9126bffe0 | ||
|
|
0488e83a38 | ||
|
|
d87ddc90e3 | ||
|
|
151bc82998 | ||
|
|
e4c21c74a5 | ||
|
|
13741a2be9 | ||
|
|
c866e89b72 | ||
|
|
8be93bc53c | ||
|
|
384b6a3e7d | ||
|
|
ba2de54c60 | ||
|
|
bd5567e24f | ||
|
|
b8e39824b5 | ||
|
|
d8c9bdbd8d | ||
|
|
80eb210af0 | ||
|
|
a295354549 | ||
|
|
749ea5dc8e | ||
|
|
f52b9e2951 | ||
|
|
d2dbb68967 | ||
|
|
d1c9009e9f | ||
|
|
d024a834f9 | ||
|
|
c0df8ac507 | ||
|
|
ab529991fd | ||
|
|
92705837ba | ||
|
|
609d5451f9 | ||
|
|
2bb2caeeed | ||
|
|
61db49bfb7 | ||
|
|
a75678d305 | ||
|
|
d418c91efa | ||
|
|
7f2da5a55d | ||
|
|
5e592ccdcb | ||
|
|
016f50fb1c | ||
|
|
fe21668a2b | ||
|
|
1aab86a317 | ||
|
|
243d23d4e2 | ||
|
|
2fe17473ae | ||
|
|
609cf8cfac | ||
|
|
678da30b09 | ||
|
|
d19412f4bb | ||
|
|
1665d6e537 | ||
|
|
fd210f2404 | ||
|
|
c33729fb44 | ||
|
|
7983bf3ee4 | ||
|
|
a09f60aea7 | ||
|
|
28b5893c21 | ||
|
|
25b47d8b6c | ||
|
|
85f5b8a7da | ||
|
|
ab9333f99a | ||
|
|
d60f8fc905 | ||
|
|
fe1f4412d8 | ||
|
|
f191533410 | ||
|
|
a894707536 | ||
|
|
d2ccc84286 | ||
|
|
f2ec43f2d2 | ||
|
|
7feccc8d9f | ||
|
|
a8bd1193ce | ||
|
|
366d1a9205 | ||
|
|
df9ed95c6b | ||
|
|
23a211362e | ||
|
|
cf91d44902 | ||
|
|
35633e21a9 | ||
|
|
ce8b8f6798 | ||
|
|
c28c80ba25 | ||
|
|
da17b1df93 | ||
|
|
f9f5865ef9 | ||
|
|
389ded9b77 | ||
|
|
faebaa59dd | ||
|
|
6b7dc2ad05 | ||
|
|
e356c9d0c8 | ||
|
|
efed2a6a5c | ||
|
|
6f138c2c51 | ||
|
|
6c43e6a533 | ||
|
|
0379afd831 | ||
|
|
b8bfdb7729 | ||
|
|
72f60ec97c | ||
|
|
1b40250750 | ||
|
|
cdf2988cb6 | ||
|
|
76415b4a0a | ||
|
|
52d00baf2b | ||
|
|
cd41db510e | ||
|
|
1afd4e8b92 | ||
|
|
ef37088c7a | ||
|
|
e71495533b | ||
|
|
e2a6d70f6a | ||
|
|
e95853b09c | ||
|
|
0537ca115e | ||
|
|
432e441972 | ||
|
|
1dae5150bd | ||
|
|
72c6f636ee | ||
|
|
e54d04277d | ||
|
|
f559f08e8d | ||
|
|
2674fb3fa7 | ||
|
|
d5d77ae7da | ||
|
|
3ae905038c | ||
|
|
6707d722e0 | ||
|
|
bc9fecf6d9 | ||
|
|
c2cb10f069 | ||
|
|
cc06d1eb0b | ||
|
|
916ff71022 | ||
|
|
9e80342e26 | ||
|
|
0fb97683bf | ||
|
|
32415bad54 | ||
|
|
d2b0bcc4a3 | ||
|
|
2f4f4193d3 | ||
|
|
7279f05a16 | ||
|
|
3962723acb | ||
|
|
125e72fa58 | ||
|
|
880cce060f | ||
|
|
0e04942111 | ||
|
|
46a88d4638 | ||
|
|
c7c39fc511 | ||
|
|
3b9bdd1916 | ||
|
|
d267be6d69 | ||
|
|
18f6a1acdc | ||
|
|
2ca41ff18f | ||
|
|
74c77bc744 | ||
|
|
1ff8cdd7a9 | ||
|
|
bd320d025a | ||
|
|
9a5b004e17 | ||
|
|
3aee059860 | ||
|
|
3dfa7f66de | ||
|
|
c2949b4773 | ||
|
|
c2d0ab4b1b | ||
|
|
de02f0bd74 | ||
|
|
e280a95619 | ||
|
|
6f06be9cc6 | ||
|
|
08745a83b4 | ||
|
|
9a262d1396 | ||
|
|
0a1b93b8fb | ||
|
|
4b638fc5da | ||
|
|
d8e34ae891 | ||
|
|
311237e49d | ||
|
|
6591bbc927 | ||
|
|
43c5717d19 | ||
|
|
61d547b2ce | ||
|
|
d7fbe54225 | ||
|
|
d0004e9fff | ||
|
|
829596a3e7 | ||
|
|
fc319f0f73 | ||
|
|
bd8ba11410 | ||
|
|
f8fcb86ad8 | ||
| 0fde9a5005 | |||
|
|
74541d7f87 |
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -1,2 +1,10 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
Moonlight/wwwroot/** linguist-vendored
|
||||
Moonlight/wwwroot/assets/js/scripts.bundle.js linguist-vendored
|
||||
Moonlight/wwwroot/assets/js/widgets.bundle.js linguist-vendored
|
||||
Moonlight/wwwroot/assets/js/theme.js linguist-vendored
|
||||
Moonlight/wwwroot/assets/css/boxicons.min.css linguist-vendored
|
||||
Moonlight/wwwroot/assets/css/style.bundle.css linguist-vendored
|
||||
Moonlight/wwwroot/assets/plugins/** linguist-vendored
|
||||
Moonlight/wwwroot/assets/fonts/** linguist-vendored
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -42,3 +42,4 @@ Desktop.ini
|
||||
|
||||
storage/
|
||||
Moonlight/publish.ps1
|
||||
Moonlight/version
|
||||
|
||||
58
Moonlight/App/ApiClients/Modrinth/ModrinthApiHelper.cs
Normal file
58
Moonlight/App/ApiClients/Modrinth/ModrinthApiHelper.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Modrinth;
|
||||
|
||||
public class ModrinthApiHelper
|
||||
{
|
||||
private readonly RestClient Client;
|
||||
|
||||
public ModrinthApiHelper()
|
||||
{
|
||||
Client = new();
|
||||
Client.AddDefaultParameter(
|
||||
new HeaderParameter("User-Agent", "Moonlight-Panel/Moonlight (admin@endelon-hosting.de)")
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<T> Get<T>(string resource)
|
||||
{
|
||||
var request = CreateRequest(resource);
|
||||
|
||||
request.Method = Method.Get;
|
||||
|
||||
var response = await Client.ExecuteAsync(request);
|
||||
|
||||
if (!response.IsSuccessful)
|
||||
{
|
||||
if (response.StatusCode != 0)
|
||||
{
|
||||
throw new ModrinthException(
|
||||
$"An error occured: ({response.StatusCode}) {response.Content}",
|
||||
(int)response.StatusCode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"An internal error occured: {response.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(response.Content!)!;
|
||||
}
|
||||
|
||||
private RestRequest CreateRequest(string resource)
|
||||
{
|
||||
var url = "https://api.modrinth.com/v2/" + resource;
|
||||
|
||||
var request = new RestRequest(url)
|
||||
{
|
||||
Timeout = 300000
|
||||
};
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Accept", "application/json");
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
19
Moonlight/App/ApiClients/Modrinth/ModrinthException.cs
Normal file
19
Moonlight/App/ApiClients/Modrinth/ModrinthException.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Moonlight.App.ApiClients.Modrinth;
|
||||
|
||||
public class ModrinthException : Exception
|
||||
{
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
public ModrinthException()
|
||||
{
|
||||
}
|
||||
|
||||
public ModrinthException(string message, int statusCode) : base(message)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
}
|
||||
|
||||
public ModrinthException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
14
Moonlight/App/ApiClients/Modrinth/Resources/Pagination.cs
Normal file
14
Moonlight/App/ApiClients/Modrinth/Resources/Pagination.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Modrinth.Resources;
|
||||
|
||||
public class Pagination
|
||||
{
|
||||
[JsonProperty("hits")] public Project[] Hits { get; set; }
|
||||
|
||||
[JsonProperty("offset")] public long Offset { get; set; }
|
||||
|
||||
[JsonProperty("limit")] public long Limit { get; set; }
|
||||
|
||||
[JsonProperty("total_hits")] public long TotalHits { get; set; }
|
||||
}
|
||||
48
Moonlight/App/ApiClients/Modrinth/Resources/Project.cs
Normal file
48
Moonlight/App/ApiClients/Modrinth/Resources/Project.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Modrinth.Resources;
|
||||
|
||||
public class Project
|
||||
{
|
||||
[JsonProperty("project_id")] public string ProjectId { get; set; }
|
||||
|
||||
[JsonProperty("project_type")] public string ProjectType { get; set; }
|
||||
|
||||
[JsonProperty("slug")] public string Slug { get; set; }
|
||||
|
||||
[JsonProperty("author")] public string Author { get; set; }
|
||||
|
||||
[JsonProperty("title")] public string Title { get; set; }
|
||||
|
||||
[JsonProperty("description")] public string Description { get; set; }
|
||||
|
||||
[JsonProperty("categories")] public string[] Categories { get; set; }
|
||||
|
||||
[JsonProperty("display_categories")] public string[] DisplayCategories { get; set; }
|
||||
|
||||
[JsonProperty("versions")] public string[] Versions { get; set; }
|
||||
|
||||
[JsonProperty("downloads")] public long Downloads { get; set; }
|
||||
|
||||
[JsonProperty("follows")] public long Follows { get; set; }
|
||||
|
||||
[JsonProperty("icon_url")] public string IconUrl { get; set; }
|
||||
|
||||
[JsonProperty("date_created")] public DateTimeOffset DateCreated { get; set; }
|
||||
|
||||
[JsonProperty("date_modified")] public DateTimeOffset DateModified { get; set; }
|
||||
|
||||
[JsonProperty("latest_version")] public string LatestVersion { get; set; }
|
||||
|
||||
[JsonProperty("license")] public string License { get; set; }
|
||||
|
||||
[JsonProperty("client_side")] public string ClientSide { get; set; }
|
||||
|
||||
[JsonProperty("server_side")] public string ServerSide { get; set; }
|
||||
|
||||
[JsonProperty("gallery")] public Uri[] Gallery { get; set; }
|
||||
|
||||
[JsonProperty("featured_gallery")] public Uri FeaturedGallery { get; set; }
|
||||
|
||||
[JsonProperty("color")] public long? Color { get; set; }
|
||||
}
|
||||
57
Moonlight/App/ApiClients/Modrinth/Resources/Version.cs
Normal file
57
Moonlight/App/ApiClients/Modrinth/Resources/Version.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Modrinth.Resources;
|
||||
|
||||
public class Version
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("version_number")]
|
||||
public string VersionNumber { get; set; }
|
||||
|
||||
[JsonProperty("changelog")]
|
||||
public string Changelog { get; set; }
|
||||
|
||||
[JsonProperty("dependencies")]
|
||||
public object[] Dependencies { get; set; }
|
||||
|
||||
[JsonProperty("game_versions")]
|
||||
public object[] GameVersions { get; set; }
|
||||
|
||||
[JsonProperty("version_type")]
|
||||
public string VersionType { get; set; }
|
||||
|
||||
[JsonProperty("loaders")]
|
||||
public object[] Loaders { get; set; }
|
||||
|
||||
[JsonProperty("featured")]
|
||||
public bool Featured { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonProperty("requested_status")]
|
||||
public string RequestedStatus { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("project_id")]
|
||||
public string ProjectId { get; set; }
|
||||
|
||||
[JsonProperty("author_id")]
|
||||
public string AuthorId { get; set; }
|
||||
|
||||
[JsonProperty("date_published")]
|
||||
public DateTime DatePublished { get; set; }
|
||||
|
||||
[JsonProperty("downloads")]
|
||||
public long Downloads { get; set; }
|
||||
|
||||
[JsonProperty("changelog_url")]
|
||||
public object ChangelogUrl { get; set; }
|
||||
|
||||
[JsonProperty("files")]
|
||||
public VersionFile[] Files { get; set; }
|
||||
}
|
||||
21
Moonlight/App/ApiClients/Modrinth/Resources/VersionFile.cs
Normal file
21
Moonlight/App/ApiClients/Modrinth/Resources/VersionFile.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Modrinth.Resources;
|
||||
|
||||
public class VersionFile
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public Uri Url { get; set; }
|
||||
|
||||
[JsonProperty("filename")]
|
||||
public string Filename { get; set; }
|
||||
|
||||
[JsonProperty("primary")]
|
||||
public bool Primary { get; set; }
|
||||
|
||||
[JsonProperty("size")]
|
||||
public long Size { get; set; }
|
||||
|
||||
[JsonProperty("file_type")]
|
||||
public string FileType { get; set; }
|
||||
}
|
||||
11
Moonlight/App/ApiClients/Telemetry/Requests/TelemetryData.cs
Normal file
11
Moonlight/App/ApiClients/Telemetry/Requests/TelemetryData.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Moonlight.App.ApiClients.Telemetry.Requests;
|
||||
|
||||
public class TelemetryData
|
||||
{
|
||||
public string AppUrl { get; set; } = "";
|
||||
public int Servers { get; set; }
|
||||
public int Nodes { get; set; }
|
||||
public int Users { get; set; }
|
||||
public int Databases { get; set; }
|
||||
public int Webspaces { get; set; }
|
||||
}
|
||||
52
Moonlight/App/ApiClients/Telemetry/TelemetryApiHelper.cs
Normal file
52
Moonlight/App/ApiClients/Telemetry/TelemetryApiHelper.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Telemetry;
|
||||
|
||||
public class TelemetryApiHelper
|
||||
{
|
||||
private readonly RestClient Client;
|
||||
|
||||
public TelemetryApiHelper()
|
||||
{
|
||||
Client = new();
|
||||
}
|
||||
|
||||
public async Task Post(string resource, object? body)
|
||||
{
|
||||
var request = CreateRequest(resource);
|
||||
|
||||
request.Method = Method.Post;
|
||||
|
||||
request.AddParameter("application/json", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
|
||||
|
||||
var response = await Client.ExecuteAsync(request);
|
||||
|
||||
if (!response.IsSuccessful)
|
||||
{
|
||||
if (response.StatusCode != 0)
|
||||
{
|
||||
throw new TelemetryException(
|
||||
$"An error occured: ({response.StatusCode}) {response.Content}",
|
||||
(int)response.StatusCode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"An internal error occured: {response.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RestRequest CreateRequest(string resource)
|
||||
{
|
||||
var url = "https://telemetry.moonlightpanel.xyz/" + resource;
|
||||
|
||||
var request = new RestRequest(url)
|
||||
{
|
||||
Timeout = 3000000
|
||||
};
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
32
Moonlight/App/ApiClients/Telemetry/TelemetryException.cs
Normal file
32
Moonlight/App/ApiClients/Telemetry/TelemetryException.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Moonlight.App.ApiClients.Telemetry;
|
||||
|
||||
[Serializable]
|
||||
public class TelemetryException : Exception
|
||||
{
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
public TelemetryException()
|
||||
{
|
||||
}
|
||||
|
||||
public TelemetryException(string message, int statusCode) : base(message)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
}
|
||||
|
||||
public TelemetryException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public TelemetryException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
protected TelemetryException(
|
||||
SerializationInfo info,
|
||||
StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,7 @@ public class WingsApiHelper
|
||||
|
||||
var request = new RestRequest(url)
|
||||
{
|
||||
Timeout = 60 * 15
|
||||
Timeout = 300000
|
||||
};
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
334
Moonlight/App/Configuration/ConfigV1.cs
Normal file
334
Moonlight/App/Configuration/ConfigV1.cs
Normal file
@@ -0,0 +1,334 @@
|
||||
using System.ComponentModel;
|
||||
using Moonlight.App.Helpers;
|
||||
|
||||
namespace Moonlight.App.Configuration;
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
public class ConfigV1
|
||||
{
|
||||
[JsonProperty("Moonlight")]
|
||||
public MoonlightData Moonlight { get; set; } = new();
|
||||
|
||||
public class MoonlightData
|
||||
{
|
||||
[JsonProperty("AppUrl")]
|
||||
[Description("The url moonlight is accesible with from the internet")]
|
||||
public string AppUrl { get; set; } = "http://your-moonlight-url-without-slash";
|
||||
|
||||
[JsonProperty("Auth")] public AuthData Auth { get; set; } = new();
|
||||
|
||||
[JsonProperty("Database")] public DatabaseData Database { get; set; } = new();
|
||||
|
||||
[JsonProperty("DiscordBotApi")] public DiscordBotApiData DiscordBotApi { get; set; } = new();
|
||||
|
||||
[JsonProperty("DiscordBot")] public DiscordBotData DiscordBot { get; set; } = new();
|
||||
|
||||
[JsonProperty("Domains")] public DomainsData Domains { get; set; } = new();
|
||||
|
||||
[JsonProperty("Html")] public HtmlData Html { get; set; } = new();
|
||||
|
||||
[JsonProperty("Marketing")] public MarketingData Marketing { get; set; } = new();
|
||||
|
||||
[JsonProperty("OAuth2")] public OAuth2Data OAuth2 { get; set; } = new();
|
||||
|
||||
[JsonProperty("Security")] public SecurityData Security { get; set; } = new();
|
||||
|
||||
[JsonProperty("Mail")] public MailData Mail { get; set; } = new();
|
||||
|
||||
[JsonProperty("Cleanup")] public CleanupData Cleanup { get; set; } = new();
|
||||
|
||||
[JsonProperty("DiscordNotifications")] public DiscordNotificationsData DiscordNotifications { get; set; } = new();
|
||||
|
||||
[JsonProperty("Statistics")] public StatisticsData Statistics { get; set; } = new();
|
||||
|
||||
[JsonProperty("Rating")] public RatingData Rating { get; set; } = new();
|
||||
|
||||
[JsonProperty("SmartDeploy")] public SmartDeployData SmartDeploy { get; set; } = new();
|
||||
|
||||
[JsonProperty("Sentry")] public SentryData Sentry { get; set; } = new();
|
||||
|
||||
[JsonProperty("Stripe")] public StripeData Stripe { get; set; } = new();
|
||||
}
|
||||
|
||||
public class StripeData
|
||||
{
|
||||
[JsonProperty("ApiKey")]
|
||||
[Description("Put here your stripe api key if you add subscriptions. Currently the only billing option is stripe which is enabled by default and cannot be turned off. This feature is still experimental")]
|
||||
public string ApiKey { get; set; } = "";
|
||||
}
|
||||
|
||||
public class AuthData
|
||||
{
|
||||
[JsonProperty("DenyLogin")]
|
||||
[Description("Prevent every new login")]
|
||||
public bool DenyLogin { get; set; } = false;
|
||||
|
||||
[JsonProperty("DenyRegister")]
|
||||
[Description("Prevent every new user to register")]
|
||||
public bool DenyRegister { get; set; } = false;
|
||||
}
|
||||
|
||||
public class CleanupData
|
||||
{
|
||||
[JsonProperty("Cpu")]
|
||||
[Description("The maximum amount of cpu usage in percent a node is allowed to use before the cleanup starts")]
|
||||
public long Cpu { get; set; } = 90;
|
||||
|
||||
[JsonProperty("Memory")]
|
||||
[Description("The minumum amount of memory in megabytes avaliable before the cleanup starts")]
|
||||
public long Memory { get; set; } = 8192;
|
||||
|
||||
[JsonProperty("Wait")]
|
||||
[Description("The delay between every cleanup check in minutes")]
|
||||
public long Wait { get; set; } = 15;
|
||||
|
||||
[JsonProperty("Uptime")]
|
||||
[Description("The maximum uptime of any server in hours before it the server restarted by the cleanup system")]
|
||||
public long Uptime { get; set; } = 6;
|
||||
|
||||
[JsonProperty("Enable")]
|
||||
[Description("The cleanup system provides a fair way for stopping unused servers and staying stable even with overallocation. A detailed explanation: docs.endelon-hosting.de/erklaerungen/cleanup")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("MinUptime")]
|
||||
[Description("The minumum uptime of a server in minutes to prevent stopping servers which just started")]
|
||||
public long MinUptime { get; set; } = 10;
|
||||
}
|
||||
|
||||
public class DatabaseData
|
||||
{
|
||||
[JsonProperty("Database")] public string Database { get; set; } = "moonlight_db";
|
||||
|
||||
[JsonProperty("Host")] public string Host { get; set; } = "your.database.host";
|
||||
|
||||
[JsonProperty("Password")]
|
||||
[Blur]
|
||||
public string Password { get; set; } = "secret";
|
||||
|
||||
[JsonProperty("Port")] public long Port { get; set; } = 3306;
|
||||
|
||||
[JsonProperty("Username")] public string Username { get; set; } = "moonlight_user";
|
||||
}
|
||||
|
||||
public class DiscordBotApiData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("Enable the discord bot api. Currently only DatBot is using this api")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("Token")]
|
||||
[Description("Specify the token the api client needs to provide")]
|
||||
[Blur]
|
||||
public string Token { get; set; } = Guid.NewGuid().ToString();
|
||||
}
|
||||
public class DiscordBotData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("The discord bot can be used to allow customers to manage their servers via discord")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("Token")]
|
||||
[Description("Your discord bot token goes here")]
|
||||
[Blur]
|
||||
public string Token { get; set; } = "discord token here";
|
||||
|
||||
[JsonProperty("PowerActions")]
|
||||
[Description("Enable actions like starting and stopping servers")]
|
||||
public bool PowerActions { get; set; } = false;
|
||||
|
||||
[JsonProperty("SendCommands")]
|
||||
[Description("Allow users to send commands to their servers")]
|
||||
public bool SendCommands { get; set; } = false;
|
||||
}
|
||||
|
||||
public class DiscordNotificationsData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("The discord notification system sends you a message everytime a event like a new support chat message is triggered with usefull data describing the event")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("WebHook")]
|
||||
[Description("The discord webhook the notifications are being sent to")]
|
||||
[Blur]
|
||||
public string WebHook { get; set; } = "http://your-discord-webhook-url";
|
||||
}
|
||||
|
||||
public class DomainsData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("This enables the domain system")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("AccountId")]
|
||||
[Description("This option specifies the cloudflare account id")]
|
||||
public string AccountId { get; set; } = "cloudflare acc id";
|
||||
|
||||
[JsonProperty("Email")]
|
||||
[Description("This specifies the cloudflare email to use for communicating with the cloudflare api")]
|
||||
public string Email { get; set; } = "cloudflare@acc.email";
|
||||
|
||||
[JsonProperty("Key")]
|
||||
[Description("Your cloudflare api key goes here")]
|
||||
[Blur]
|
||||
public string Key { get; set; } = "secret";
|
||||
}
|
||||
|
||||
public class HtmlData
|
||||
{
|
||||
[JsonProperty("Headers")] public HeadersData Headers { get; set; } = new();
|
||||
}
|
||||
|
||||
public class HeadersData
|
||||
{
|
||||
[JsonProperty("Color")]
|
||||
[Description("This specifies the color of the embed generated by platforms like discord when someone posts a link to your moonlight instance")]
|
||||
public string Color { get; set; } = "#4b27e8";
|
||||
|
||||
[JsonProperty("Description")]
|
||||
[Description("This specifies the description text of the embed generated by platforms like discord when someone posts a link to your moonlight instance and can also help google to index your moonlight instance correctly")]
|
||||
public string Description { get; set; } = "the next generation hosting panel";
|
||||
|
||||
[JsonProperty("Keywords")]
|
||||
[Description("To help search engines like google to index your moonlight instance correctly you can specify keywords seperated by a comma here")]
|
||||
public string Keywords { get; set; } = "moonlight";
|
||||
|
||||
[JsonProperty("Title")]
|
||||
[Description("This specifies the title of the embed generated by platforms like discord when someone posts a link to your moonlight instance")]
|
||||
public string Title { get; set; } = "Moonlight - endelon.link";
|
||||
}
|
||||
|
||||
public class MailData
|
||||
{
|
||||
[JsonProperty("Email")] public string Email { get; set; } = "username@your.mail.host";
|
||||
|
||||
[JsonProperty("Server")] public string Server { get; set; } = "your.mail.host";
|
||||
|
||||
[JsonProperty("Password")]
|
||||
[Blur]
|
||||
public string Password { get; set; } = "secret";
|
||||
|
||||
[JsonProperty("Port")] public int Port { get; set; } = 465;
|
||||
|
||||
[JsonProperty("Ssl")] public bool Ssl { get; set; } = true;
|
||||
}
|
||||
|
||||
public class MarketingData
|
||||
{
|
||||
[JsonProperty("BrandName")] public string BrandName { get; set; } = "Endelon Hosting";
|
||||
|
||||
[JsonProperty("Imprint")] public string Imprint { get; set; } = "https://your-site.xyz/imprint";
|
||||
|
||||
[JsonProperty("Privacy")] public string Privacy { get; set; } = "https://your-site.xyz/privacy";
|
||||
[JsonProperty("About")] public string About { get; set; } = "https://your-site.xyz/about";
|
||||
[JsonProperty("Website")] public string Website { get; set; } = "https://your-site.xyz";
|
||||
}
|
||||
|
||||
public class OAuth2Data
|
||||
{
|
||||
[JsonProperty("OverrideUrl")]
|
||||
[Description("This overrides the redirect url which would be typicaly the app url")]
|
||||
public string OverrideUrl { get; set; } = "https://only-for-development.cases";
|
||||
|
||||
[JsonProperty("EnableOverrideUrl")]
|
||||
[Description("This enables the url override")]
|
||||
public bool EnableOverrideUrl { get; set; } = false;
|
||||
|
||||
[JsonProperty("Providers")]
|
||||
public OAuth2ProviderData[] Providers { get; set; } = Array.Empty<OAuth2ProviderData>();
|
||||
}
|
||||
|
||||
public class OAuth2ProviderData
|
||||
{
|
||||
[JsonProperty("Id")] public string Id { get; set; }
|
||||
|
||||
[JsonProperty("ClientId")] public string ClientId { get; set; }
|
||||
|
||||
[JsonProperty("ClientSecret")]
|
||||
[Blur]
|
||||
public string ClientSecret { get; set; }
|
||||
}
|
||||
|
||||
public class RatingData
|
||||
{
|
||||
[JsonProperty("Enabled")]
|
||||
[Description("The rating systems shows a user who is registered longer than the set amout of days a popup to rate this platform if he hasnt rated it before")]
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
||||
[JsonProperty("Url")]
|
||||
[Description("This is the url a user who rated above a set limit is shown to rate you again. Its recommended to put your google or trustpilot rate link here")]
|
||||
public string Url { get; set; } = "https://link-to-google-or-smth";
|
||||
|
||||
[JsonProperty("MinRating")]
|
||||
[Description("The minimum star count on the rating ranging from 1 to 5")]
|
||||
public int MinRating { get; set; } = 4;
|
||||
|
||||
[JsonProperty("DaysSince")]
|
||||
[Description("The days a user has to be registered to even be able to get this popup")]
|
||||
public int DaysSince { get; set; } = 5;
|
||||
}
|
||||
|
||||
public class SecurityData
|
||||
{
|
||||
[JsonProperty("Token")]
|
||||
[Description("This is the moonlight app token. It is used to encrypt and decrypt data and validte tokens and sessions")]
|
||||
[Blur]
|
||||
public string Token { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
[JsonProperty("ReCaptcha")] public ReCaptchaData ReCaptcha { get; set; } = new();
|
||||
}
|
||||
|
||||
public class ReCaptchaData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("Enables repatcha at places like the register page. For information how to get your recaptcha credentails go to google.com/recaptcha/about/")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("SiteKey")]
|
||||
[Blur]
|
||||
public string SiteKey { get; set; } = "recaptcha site key here";
|
||||
|
||||
[JsonProperty("SecretKey")]
|
||||
[Blur]
|
||||
public string SecretKey { get; set; } = "recaptcha secret here";
|
||||
}
|
||||
|
||||
public class SentryData
|
||||
{
|
||||
[JsonProperty("Enable")]
|
||||
[Description("Sentry is a way to monitor application crashes and performance issues in real time. Enable this option only if you set a sentry dsn")]
|
||||
public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("Dsn")]
|
||||
[Description("The dsn is the key moonlight needs to communicate with your sentry instance")]
|
||||
[Blur]
|
||||
public string Dsn { get; set; } = "http://your-sentry-url-here";
|
||||
}
|
||||
|
||||
public class SmartDeployData
|
||||
{
|
||||
[JsonProperty("Server")] public SmartDeployServerData Server { get; set; } = new();
|
||||
}
|
||||
|
||||
public class SmartDeployServerData
|
||||
{
|
||||
[JsonProperty("EnableOverride")] public bool EnableOverride { get; set; } = false;
|
||||
|
||||
[JsonProperty("OverrideNode")] public long OverrideNode { get; set; } = 1;
|
||||
}
|
||||
|
||||
public class StatisticsData
|
||||
{
|
||||
[JsonProperty("Enabled")] public bool Enabled { get; set; } = false;
|
||||
|
||||
[JsonProperty("Wait")] public long Wait { get; set; } = 15;
|
||||
}
|
||||
|
||||
public class SellPassData
|
||||
{
|
||||
[JsonProperty("Enable")] public bool Enable { get; set; } = false;
|
||||
|
||||
[JsonProperty("Url")] public string Url { get; set; } = "https://not-implemented-yet";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Database.Entities.LogsEntries;
|
||||
using Moonlight.App.Database.Entities.Notification;
|
||||
using Moonlight.App.Database.Interceptors;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Database;
|
||||
@@ -27,10 +25,6 @@ public class DataContext : DbContext
|
||||
public DbSet<ServerVariable> ServerVariables { get; set; }
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<LoadingMessage> LoadingMessages { get; set; }
|
||||
public DbSet<AuditLogEntry> AuditLog { get; set; }
|
||||
public DbSet<ErrorLogEntry> ErrorLog { get; set; }
|
||||
public DbSet<SecurityLogEntry> SecurityLog { get; set; }
|
||||
|
||||
public DbSet<SharedDomain> SharedDomains { get; set; }
|
||||
public DbSet<Domain> Domains { get; set; }
|
||||
public DbSet<Revoke> Revokes { get; set; }
|
||||
@@ -46,20 +40,22 @@ public class DataContext : DbContext
|
||||
public DbSet<WebSpace> WebSpaces { get; set; }
|
||||
public DbSet<SupportChatMessage> SupportChatMessages { get; set; }
|
||||
public DbSet<IpBan> IpBans { get; set; }
|
||||
public DbSet<PermissionGroup> PermissionGroups { get; set; }
|
||||
public DbSet<SecurityLog> SecurityLogs { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
if (!optionsBuilder.IsConfigured)
|
||||
{
|
||||
var config = ConfigService
|
||||
.GetSection("Moonlight")
|
||||
.GetSection("Database");
|
||||
.Get()
|
||||
.Moonlight.Database;
|
||||
|
||||
var connectionString = $"host={config.GetValue<string>("Host")};" +
|
||||
$"port={config.GetValue<int>("Port")};" +
|
||||
$"database={config.GetValue<string>("Database")};" +
|
||||
$"uid={config.GetValue<string>("Username")};" +
|
||||
$"pwd={config.GetValue<string>("Password")}";
|
||||
var connectionString = $"host={config.Host};" +
|
||||
$"port={config.Port};" +
|
||||
$"database={config.Database};" +
|
||||
$"uid={config.Username};" +
|
||||
$"pwd={config.Password}";
|
||||
|
||||
optionsBuilder.UseMySql(
|
||||
connectionString,
|
||||
|
||||
@@ -20,4 +20,5 @@ public class Image
|
||||
public List<DockerImage> DockerImages { get; set; } = new();
|
||||
public List<ImageVariable> Variables { get; set; } = new();
|
||||
public string TagsJson { get; set; } = "";
|
||||
public string BackgroundImageUrl { get; set; } = "";
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Database.Entities.LogsEntries;
|
||||
|
||||
public class AuditLogEntry
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public AuditLogType Type { get; set; }
|
||||
public string JsonData { get; set; } = "";
|
||||
public bool System { get; set; }
|
||||
public string Ip { get; set; } = "";
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Moonlight.App.Database.Entities.LogsEntries;
|
||||
|
||||
public class ErrorLogEntry
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Stacktrace { get; set; } = "";
|
||||
public bool System { get; set; }
|
||||
public string JsonData { get; set; } = "";
|
||||
public string Ip { get; set; } = "";
|
||||
public string Class { get; set; } = "";
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Database.Entities.LogsEntries;
|
||||
|
||||
public class SecurityLogEntry
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool System { get; set; }
|
||||
public string Ip { get; set; } = "";
|
||||
public SecurityLogType Type { get; set; }
|
||||
public string JsonData { get; set; } = "";
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
8
Moonlight/App/Database/Entities/PermissionGroup.cs
Normal file
8
Moonlight/App/Database/Entities/PermissionGroup.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
public class PermissionGroup
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public byte[] Permissions { get; set; } = Array.Empty<byte>();
|
||||
}
|
||||
8
Moonlight/App/Database/Entities/SecurityLog.cs
Normal file
8
Moonlight/App/Database/Entities/SecurityLog.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
public class SecurityLog
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Text { get; set; } = "";
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -13,6 +13,8 @@ public class Server
|
||||
public string OverrideStartup { get; set; } = "";
|
||||
public bool Installing { get; set; } = false;
|
||||
public bool Suspended { get; set; } = false;
|
||||
public bool IsArchived { get; set; } = false;
|
||||
public ServerBackup? Archive { get; set; } = null;
|
||||
|
||||
public List<ServerVariable> Variables { get; set; } = new();
|
||||
public List<ServerBackup> Backups { get; set; } = new();
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
public class Subscription
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public Currency Currency { get; set; } = Currency.USD;
|
||||
public double Price { get; set; }
|
||||
public string StripeProductId { get; set; } = "";
|
||||
public string StripePriceId { get; set; } = "";
|
||||
public string LimitsJson { get; set; } = "";
|
||||
public int Duration { get; set; } = 30;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Moonlight.App.Models.Misc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
@@ -24,6 +25,8 @@ public class User
|
||||
|
||||
public string Country { get; set; } = "";
|
||||
|
||||
public string ServerListLayoutJson { get; set; } = "";
|
||||
|
||||
// States
|
||||
|
||||
public UserStatus Status { get; set; } = UserStatus.Unverified;
|
||||
@@ -31,11 +34,14 @@ public class User
|
||||
public bool SupportPending { get; set; } = false;
|
||||
public bool HasRated { get; set; } = false;
|
||||
public int Rating { get; set; } = 0;
|
||||
public bool StreamerMode { get; set; } = false;
|
||||
|
||||
// Security
|
||||
public bool TotpEnabled { get; set; } = false;
|
||||
public string TotpSecret { get; set; } = "";
|
||||
public DateTime TokenValidTime { get; set; } = DateTime.UtcNow;
|
||||
public byte[] Permissions { get; set; } = Array.Empty<byte>();
|
||||
public PermissionGroup? PermissionGroup { get; set; }
|
||||
|
||||
// Discord
|
||||
public ulong DiscordId { get; set; }
|
||||
@@ -43,10 +49,15 @@ public class User
|
||||
// Date stuff
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime LastVisitedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// Subscriptions
|
||||
|
||||
public Subscription? CurrentSubscription { get; set; } = null;
|
||||
public DateTime SubscriptionSince { get; set; } = DateTime.Now;
|
||||
public int SubscriptionDuration { get; set; }
|
||||
public DateTime SubscriptionSince { get; set; } = DateTime.UtcNow;
|
||||
public DateTime SubscriptionExpires { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// Ip logs
|
||||
public string RegisterIp { get; set; } = "";
|
||||
public string LastIp { get; set; } = "";
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Data.Common;
|
||||
using Logging.Net;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Moonlight.App.Helpers;
|
||||
|
||||
namespace Moonlight.App.Database.Interceptors;
|
||||
|
||||
|
||||
1056
Moonlight/App/Database/Migrations/20230609202138_AddBackgroundImageUrlImage.Designer.cs
generated
Normal file
1056
Moonlight/App/Database/Migrations/20230609202138_AddBackgroundImageUrlImage.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddBackgroundImageUrlImage : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "BackgroundImageUrl",
|
||||
table: "Images",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BackgroundImageUrl",
|
||||
table: "Images");
|
||||
}
|
||||
}
|
||||
}
|
||||
1059
Moonlight/App/Database/Migrations/20230611152138_AddLastVisitedTimestamp.Designer.cs
generated
Normal file
1059
Moonlight/App/Database/Migrations/20230611152138_AddLastVisitedTimestamp.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddLastVisitedTimestamp : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "LastVisitedAt",
|
||||
table: "Users",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LastVisitedAt",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1073
Moonlight/App/Database/Migrations/20230614010621_AddedServerAchive.Designer.cs
generated
Normal file
1073
Moonlight/App/Database/Migrations/20230614010621_AddedServerAchive.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedServerAchive : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ArchiveId",
|
||||
table: "Servers",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsArchived",
|
||||
table: "Servers",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Servers_ArchiveId",
|
||||
table: "Servers",
|
||||
column: "ArchiveId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Servers_ServerBackups_ArchiveId",
|
||||
table: "Servers",
|
||||
column: "ArchiveId",
|
||||
principalTable: "ServerBackups",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Servers_ServerBackups_ArchiveId",
|
||||
table: "Servers");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Servers_ArchiveId",
|
||||
table: "Servers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ArchiveId",
|
||||
table: "Servers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsArchived",
|
||||
table: "Servers");
|
||||
}
|
||||
}
|
||||
}
|
||||
1077
Moonlight/App/Database/Migrations/20230623235512_AddedServerListLayoutToUser.Designer.cs
generated
Normal file
1077
Moonlight/App/Database/Migrations/20230623235512_AddedServerListLayoutToUser.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedServerListLayoutToUser : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ServerListLayoutJson",
|
||||
table: "Users",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ServerListLayoutJson",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1080
Moonlight/App/Database/Migrations/20230625190428_AddedStreamerMode.Designer.cs
generated
Normal file
1080
Moonlight/App/Database/Migrations/20230625190428_AddedStreamerMode.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedStreamerMode : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "StreamerMode",
|
||||
table: "Users",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "StreamerMode",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1088
Moonlight/App/Database/Migrations/20230703175432_AddedIpLogsForUser.Designer.cs
generated
Normal file
1088
Moonlight/App/Database/Migrations/20230703175432_AddedIpLogsForUser.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedIpLogsForUser : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "LastIp",
|
||||
table: "Users",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "RegisterIp",
|
||||
table: "Users",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LastIp",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "RegisterIp",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1105
Moonlight/App/Database/Migrations/20230705171914_AddedStripeIntegration.Designer.cs
generated
Normal file
1105
Moonlight/App/Database/Migrations/20230705171914_AddedStripeIntegration.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedStripeIntegration : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SubscriptionDuration",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "SubscriptionExpires",
|
||||
table: "Users",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Currency",
|
||||
table: "Subscriptions",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Duration",
|
||||
table: "Subscriptions",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "Price",
|
||||
table: "Subscriptions",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "StripePriceId",
|
||||
table: "Subscriptions",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "StripeProductId",
|
||||
table: "Subscriptions",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SubscriptionExpires",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Currency",
|
||||
table: "Subscriptions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Duration",
|
||||
table: "Subscriptions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Price",
|
||||
table: "Subscriptions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "StripePriceId",
|
||||
table: "Subscriptions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "StripeProductId",
|
||||
table: "Subscriptions");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "SubscriptionDuration",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
1109
Moonlight/App/Database/Migrations/20230715095531_AddPermissions.Designer.cs
generated
Normal file
1109
Moonlight/App/Database/Migrations/20230715095531_AddPermissions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPermissions : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "Permissions",
|
||||
table: "Users",
|
||||
type: "longblob",
|
||||
nullable: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1139
Moonlight/App/Database/Migrations/20230715214550_AddPermissionGroup.Designer.cs
generated
Normal file
1139
Moonlight/App/Database/Migrations/20230715214550_AddPermissionGroup.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPermissionGroup : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "PermissionGroupId",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PermissionGroups",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Permissions = table.Column<byte[]>(type: "longblob", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PermissionGroups", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_PermissionGroupId",
|
||||
table: "Users",
|
||||
column: "PermissionGroupId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Users_PermissionGroups_PermissionGroupId",
|
||||
table: "Users",
|
||||
column: "PermissionGroupId",
|
||||
principalTable: "PermissionGroups",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Users_PermissionGroups_PermissionGroupId",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PermissionGroups");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Users_PermissionGroupId",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PermissionGroupId",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
1068
Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs
generated
Normal file
1068
Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RemovedOldLogsAndAddedErrorLog : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AuditLog");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ErrorLog");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SecurityLog");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SecurityLogs",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Text = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SecurityLogs", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "SecurityLogs");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AuditLog",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
JsonData = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
System = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AuditLog", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ErrorLog",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Class = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
JsonData = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Stacktrace = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
System = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ErrorLog", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SecurityLog",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
JsonData = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
System = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SecurityLog", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,10 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.Property<int>("Allocations")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("BackgroundImageUrl")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ConfigFiles")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
@@ -237,95 +241,6 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.ToTable("LoadingMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Ip")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("JsonData")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("System")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AuditLog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Class")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Ip")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("JsonData")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Stacktrace")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("System")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ErrorLog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Ip")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("JsonData")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("System")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SecurityLog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -471,6 +386,25 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.ToTable("NotificationClients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.PermissionGroup", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<byte[]>("Permissions")
|
||||
.IsRequired()
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PermissionGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -486,12 +420,33 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.ToTable("Revokes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.SecurityLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("SecurityLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("ArchiveId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Cpu")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -507,6 +462,9 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.Property<bool>("Installing")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsArchived")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsCleanupException")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
@@ -538,6 +496,8 @@ namespace Moonlight.App.Database.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ArchiveId");
|
||||
|
||||
b.HasIndex("ImageId");
|
||||
|
||||
b.HasIndex("MainAllocationId");
|
||||
@@ -651,10 +611,16 @@ namespace Moonlight.App.Database.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Currency")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("LimitsJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
@@ -663,6 +629,17 @@ namespace Moonlight.App.Database.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("double");
|
||||
|
||||
b.Property<string>("StripePriceId")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("StripeProductId")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Subscriptions");
|
||||
@@ -754,17 +731,39 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.Property<bool>("HasRated")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("LastIp")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("LastVisitedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("PermissionGroupId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<byte[]>("Permissions")
|
||||
.IsRequired()
|
||||
.HasColumnType("longblob");
|
||||
|
||||
b.Property<int>("Rating")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("RegisterIp")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ServerListLayoutJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("State")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
@@ -772,8 +771,11 @@ namespace Moonlight.App.Database.Migrations
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SubscriptionDuration")
|
||||
.HasColumnType("int");
|
||||
b.Property<bool>("StreamerMode")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTime>("SubscriptionExpires")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime>("SubscriptionSince")
|
||||
.HasColumnType("datetime(6)");
|
||||
@@ -798,6 +800,8 @@ namespace Moonlight.App.Database.Migrations
|
||||
|
||||
b.HasIndex("CurrentSubscriptionId");
|
||||
|
||||
b.HasIndex("PermissionGroupId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
@@ -928,6 +932,10 @@ namespace Moonlight.App.Database.Migrations
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.ServerBackup", "Archive")
|
||||
.WithMany()
|
||||
.HasForeignKey("ArchiveId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||
.WithMany()
|
||||
.HasForeignKey("ImageId")
|
||||
@@ -950,6 +958,8 @@ namespace Moonlight.App.Database.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Archive");
|
||||
|
||||
b.Navigation("Image");
|
||||
|
||||
b.Navigation("MainAllocation");
|
||||
@@ -996,7 +1006,13 @@ namespace Moonlight.App.Database.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("CurrentSubscriptionId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.PermissionGroup", "PermissionGroup")
|
||||
.WithMany()
|
||||
.HasForeignKey("PermissionGroupId");
|
||||
|
||||
b.Navigation("CurrentSubscription");
|
||||
|
||||
b.Navigation("PermissionGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b =>
|
||||
|
||||
58
Moonlight/App/Diagnostics/HealthChecks/DaemonHealthCheck.cs
Normal file
58
Moonlight/App/Diagnostics/HealthChecks/DaemonHealthCheck.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Diagnostics.HealthChecks;
|
||||
|
||||
public class DaemonHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly Repository<Node> NodeRepository;
|
||||
private readonly NodeService NodeService;
|
||||
|
||||
public DaemonHealthCheck(Repository<Node> nodeRepository, NodeService nodeService)
|
||||
{
|
||||
NodeRepository = nodeRepository;
|
||||
NodeService = nodeService;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var nodes = NodeRepository.Get().ToArray();
|
||||
|
||||
var results = new Dictionary<Node, bool>();
|
||||
var healthCheckData = new Dictionary<string, object>();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
await NodeService.GetCpuMetrics(node);
|
||||
|
||||
results.Add(node, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
results.Add(node, false);
|
||||
healthCheckData.Add(node.Name, e.ToStringDemystified());
|
||||
}
|
||||
}
|
||||
|
||||
var offlineNodes = results
|
||||
.Where(x => !x.Value)
|
||||
.ToArray();
|
||||
|
||||
if (offlineNodes.Length == nodes.Length)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("All node daemons are offline", null, healthCheckData);
|
||||
}
|
||||
|
||||
if (offlineNodes.Length == 0)
|
||||
{
|
||||
return HealthCheckResult.Healthy("All node daemons are online");
|
||||
}
|
||||
|
||||
return HealthCheckResult.Degraded($"{offlineNodes.Length} node daemons are offline", null, healthCheckData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
namespace Moonlight.App.Diagnostics.HealthChecks;
|
||||
|
||||
public class DatabaseHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly DataContext DataContext;
|
||||
|
||||
public DatabaseHealthCheck(DataContext dataContext)
|
||||
{
|
||||
DataContext = dataContext;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
try
|
||||
{
|
||||
await DataContext.Database.OpenConnectionAsync(cancellationToken);
|
||||
await DataContext.Database.CloseConnectionAsync();
|
||||
|
||||
return HealthCheckResult.Healthy("Database is online");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Database is offline", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Moonlight/App/Diagnostics/HealthChecks/NodeHealthCheck.cs
Normal file
58
Moonlight/App/Diagnostics/HealthChecks/NodeHealthCheck.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Diagnostics.HealthChecks;
|
||||
|
||||
public class NodeHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly Repository<Node> NodeRepository;
|
||||
private readonly NodeService NodeService;
|
||||
|
||||
public NodeHealthCheck(Repository<Node> nodeRepository, NodeService nodeService)
|
||||
{
|
||||
NodeRepository = nodeRepository;
|
||||
NodeService = nodeService;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var nodes = NodeRepository.Get().ToArray();
|
||||
|
||||
var results = new Dictionary<Node, bool>();
|
||||
var healthCheckData = new Dictionary<string, object>();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
try
|
||||
{
|
||||
await NodeService.GetStatus(node);
|
||||
|
||||
results.Add(node, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
results.Add(node, false);
|
||||
healthCheckData.Add(node.Name, e.ToStringDemystified());
|
||||
}
|
||||
}
|
||||
|
||||
var offlineNodes = results
|
||||
.Where(x => !x.Value)
|
||||
.ToArray();
|
||||
|
||||
if (offlineNodes.Length == nodes.Length)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("All nodes are offline", null, healthCheckData);
|
||||
}
|
||||
|
||||
if (offlineNodes.Length == 0)
|
||||
{
|
||||
return HealthCheckResult.Healthy("All nodes are online");
|
||||
}
|
||||
|
||||
return HealthCheckResult.Degraded($"{offlineNodes.Length} nodes are offline", null, healthCheckData);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.Helpers;
|
||||
|
||||
namespace Moonlight.App.Events;
|
||||
|
||||
@@ -112,4 +112,22 @@ public class EventSystem
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<T> WaitForEvent<T>(string id, object handle, Func<T, bool> filter)
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<T>();
|
||||
|
||||
Func<T, Task> action = async data =>
|
||||
{
|
||||
if (filter.Invoke(data))
|
||||
{
|
||||
taskCompletionSource.SetResult(data);
|
||||
await Off(id, handle);
|
||||
}
|
||||
};
|
||||
|
||||
On<T>(id, handle, action);
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace Moonlight.App.Exceptions;
|
||||
[Serializable]
|
||||
public class DisplayException : Exception
|
||||
{
|
||||
public bool DoNotTranslate { get; set; } = false;
|
||||
|
||||
//
|
||||
// For guidelines regarding the creation of new exception types, see
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
|
||||
@@ -20,6 +22,11 @@ public class DisplayException : Exception
|
||||
{
|
||||
}
|
||||
|
||||
public DisplayException(string message, bool doNotTranslate) : base(message)
|
||||
{
|
||||
DoNotTranslate = doNotTranslate;
|
||||
}
|
||||
|
||||
public DisplayException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
30
Moonlight/App/Extensions/JSRuntimeExtensions.cs
Normal file
30
Moonlight/App/Extensions/JSRuntimeExtensions.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Moonlight.App.Extensions;
|
||||
|
||||
public static class JSRuntimeExtensions
|
||||
{
|
||||
public static async Task InvokeVoidSafeAsync(this IJSRuntime jsRuntime, string method, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
await jsRuntime.InvokeVoidAsync(method, args);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static void InvokeVoidSafe(this IJSRuntime jsRuntime, string method, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
jsRuntime.InvokeVoidAsync(method, args);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Moonlight/App/Helpers/AvgHelper.cs
Normal file
39
Moonlight/App/Helpers/AvgHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class AvgHelper
|
||||
{
|
||||
public static StatisticsData[] Calculate(StatisticsData[] data, int splitSize = 40)
|
||||
{
|
||||
if (data.Length <= splitSize)
|
||||
return data;
|
||||
|
||||
var result = new List<StatisticsData>();
|
||||
|
||||
var i = data.Length / (float)splitSize;
|
||||
var pc = (int)Math.Round(i);
|
||||
|
||||
foreach (var part in data.Chunk(pc))
|
||||
{
|
||||
double d = 0;
|
||||
var res = new StatisticsData();
|
||||
|
||||
foreach (var entry in part)
|
||||
{
|
||||
d += entry.Value;
|
||||
}
|
||||
|
||||
res.Chart = part.First().Chart;
|
||||
res.Date = part.First().Date;
|
||||
|
||||
if (d == 0)
|
||||
res.Value = 0;
|
||||
|
||||
res.Value = d / part.Length;
|
||||
result.Add(res);
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
88
Moonlight/App/Helpers/BitHelper.cs
Normal file
88
Moonlight/App/Helpers/BitHelper.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class BitHelper
|
||||
{
|
||||
public static bool ReadBit(byte[] byteArray, int bitIndex)
|
||||
{
|
||||
if (bitIndex < 0)
|
||||
throw new ArgumentOutOfRangeException("bitIndex");
|
||||
|
||||
int byteIndex = bitIndex / 8;
|
||||
if (byteIndex >= byteArray.Length)
|
||||
throw new ArgumentOutOfRangeException("bitIndex");
|
||||
|
||||
int bitNumber = bitIndex % 8;
|
||||
byte mask = (byte)(1 << bitNumber);
|
||||
|
||||
return (byteArray[byteIndex] & mask) != 0;
|
||||
}
|
||||
|
||||
public static byte[] WriteBit(byte[] byteArray, int bitIndex, bool value)
|
||||
{
|
||||
if (bitIndex < 0)
|
||||
throw new ArgumentOutOfRangeException("bitIndex");
|
||||
|
||||
int byteIndex = bitIndex / 8;
|
||||
byte[] resultArray;
|
||||
|
||||
if (byteIndex >= byteArray.Length)
|
||||
{
|
||||
// Create a new array with increased size and copy elements from old array
|
||||
resultArray = new byte[byteIndex + 1];
|
||||
Array.Copy(byteArray, resultArray, byteArray.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new array and copy elements from old array
|
||||
resultArray = new byte[byteArray.Length];
|
||||
Array.Copy(byteArray, resultArray, byteArray.Length);
|
||||
}
|
||||
|
||||
int bitNumber = bitIndex % 8;
|
||||
byte mask = (byte)(1 << bitNumber);
|
||||
|
||||
if (value)
|
||||
resultArray[byteIndex] |= mask; // Set the bit to 1
|
||||
else
|
||||
resultArray[byteIndex] &= (byte)~mask; // Set the bit to 0
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
public static byte[] OverwriteByteArrays(byte[] targetArray, byte[] overwriteArray)
|
||||
{
|
||||
int targetLength = targetArray.Length;
|
||||
int overwriteLength = overwriteArray.Length;
|
||||
|
||||
int maxLength = Math.Max(targetLength, overwriteLength);
|
||||
|
||||
byte[] resultArray = new byte[maxLength];
|
||||
|
||||
for (int i = 0; i < maxLength; i++)
|
||||
{
|
||||
byte targetByte = i < targetLength ? targetArray[i] : (byte)0;
|
||||
byte overwriteByte = i < overwriteLength ? overwriteArray[i] : (byte)0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
bool overwriteBit = (overwriteByte & (1 << j)) != 0;
|
||||
if (i < targetLength)
|
||||
{
|
||||
bool targetBit = (targetByte & (1 << j)) != 0;
|
||||
if (overwriteBit)
|
||||
{
|
||||
targetByte = targetBit ? (byte)(targetByte | (1 << j)) : (byte)(targetByte & ~(1 << j));
|
||||
}
|
||||
}
|
||||
else if (overwriteBit)
|
||||
{
|
||||
targetByte |= (byte)(1 << j);
|
||||
}
|
||||
}
|
||||
|
||||
resultArray[i] = targetByte;
|
||||
}
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
}
|
||||
6
Moonlight/App/Helpers/BlurAttribute.cs
Normal file
6
Moonlight/App/Helpers/BlurAttribute.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class BlurAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using Logging.Net;
|
||||
using Logging.Net.Loggers.SB;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using ILogger = Logging.Net.ILogger;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class CacheLogger : ILogger
|
||||
{
|
||||
private SBLogger SbLogger = new();
|
||||
private List<LogEntry> Messages = new();
|
||||
|
||||
public LogEntry[] GetMessages()
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
var result = new LogEntry[Messages.Count];
|
||||
Messages.CopyTo(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear(int messages)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.RemoveRange(0, Math.Min(messages, Messages.Count));
|
||||
}
|
||||
}
|
||||
|
||||
public void Info(string? s)
|
||||
{
|
||||
if (s == null)
|
||||
return;
|
||||
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "info",
|
||||
Message = s
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.Info(s);
|
||||
}
|
||||
|
||||
public void Debug(string? s)
|
||||
{
|
||||
if (s == null)
|
||||
return;
|
||||
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "debug",
|
||||
Message = s
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.Debug(s);
|
||||
}
|
||||
|
||||
public void Warn(string? s)
|
||||
{
|
||||
if (s == null)
|
||||
return;
|
||||
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "warn",
|
||||
Message = s
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.Warn(s);
|
||||
}
|
||||
|
||||
public void Error(string? s)
|
||||
{
|
||||
if (s == null)
|
||||
return;
|
||||
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "error",
|
||||
Message = s
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.Error(s);
|
||||
}
|
||||
|
||||
public void Fatal(string? s)
|
||||
{
|
||||
if (s == null)
|
||||
return;
|
||||
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "fatal",
|
||||
Message = s
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.Fatal(s);
|
||||
}
|
||||
|
||||
public void InfoEx(Exception ex)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "info",
|
||||
Message = ex.ToStringDemystified()
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.InfoEx(ex);
|
||||
}
|
||||
|
||||
public void DebugEx(Exception ex)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "debug",
|
||||
Message = ex.ToStringDemystified()
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.DebugEx(ex);
|
||||
}
|
||||
|
||||
public void WarnEx(Exception ex)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "warn",
|
||||
Message = ex.ToStringDemystified()
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.WarnEx(ex);
|
||||
}
|
||||
|
||||
public void ErrorEx(Exception ex)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "error",
|
||||
Message = ex.ToStringDemystified()
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.ErrorEx(ex);
|
||||
}
|
||||
|
||||
public void FatalEx(Exception ex)
|
||||
{
|
||||
lock (Messages)
|
||||
{
|
||||
Messages.Add(new()
|
||||
{
|
||||
Level = "fatal",
|
||||
Message = ex.ToStringDemystified()
|
||||
});
|
||||
}
|
||||
|
||||
SbLogger.FatalEx(ex);
|
||||
}
|
||||
|
||||
public LoggingConfiguration GetErrorConfiguration()
|
||||
{
|
||||
return SbLogger.GetErrorConfiguration();
|
||||
}
|
||||
|
||||
public void SetErrorConfiguration(LoggingConfiguration configuration)
|
||||
{
|
||||
SbLogger.SetErrorConfiguration(configuration);
|
||||
}
|
||||
|
||||
public LoggingConfiguration GetFatalConfiguration()
|
||||
{
|
||||
return SbLogger.GetFatalConfiguration();
|
||||
}
|
||||
|
||||
public void SetFatalConfiguration(LoggingConfiguration configuration)
|
||||
{
|
||||
SbLogger.SetFatalConfiguration(configuration);
|
||||
}
|
||||
|
||||
public LoggingConfiguration GetWarnConfiguration()
|
||||
{
|
||||
return SbLogger.GetWarnConfiguration();
|
||||
}
|
||||
|
||||
public void SetWarnConfiguration(LoggingConfiguration configuration)
|
||||
{
|
||||
SbLogger.SetWarnConfiguration(configuration);
|
||||
}
|
||||
|
||||
public LoggingConfiguration GetInfoConfiguration()
|
||||
{
|
||||
return SbLogger.GetInfoConfiguration();
|
||||
}
|
||||
|
||||
public void SetInfoConfiguration(LoggingConfiguration configuration)
|
||||
{
|
||||
SbLogger.SetInfoConfiguration(configuration);
|
||||
}
|
||||
|
||||
public LoggingConfiguration GetDebugConfiguration()
|
||||
{
|
||||
return SbLogger.GetDebugConfiguration();
|
||||
}
|
||||
|
||||
public void SetDebugConfiguration(LoggingConfiguration configuration)
|
||||
{
|
||||
SbLogger.SetDebugConfiguration(configuration);
|
||||
}
|
||||
|
||||
public ILoggingAddition GetAddition()
|
||||
{
|
||||
return SbLogger.GetAddition();
|
||||
}
|
||||
|
||||
public void SetAddition(ILoggingAddition addition)
|
||||
{
|
||||
SbLogger.SetAddition(addition);
|
||||
}
|
||||
|
||||
public bool LogCallingClass
|
||||
{
|
||||
get => SbLogger.LogCallingClass;
|
||||
set => SbLogger.LogCallingClass = value;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using Logging.Net;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database;
|
||||
using Moonlight.App.Services;
|
||||
@@ -67,34 +66,45 @@ public class DatabaseCheckupService
|
||||
var configService = new ConfigService(new StorageService());
|
||||
var dateTimeService = new DateTimeService();
|
||||
|
||||
var config = configService
|
||||
.GetSection("Moonlight")
|
||||
.GetSection("Database");
|
||||
var config = configService.Get().Moonlight.Database;
|
||||
|
||||
var connectionString = $"host={config.GetValue<string>("Host")};" +
|
||||
$"port={config.GetValue<int>("Port")};" +
|
||||
$"database={config.GetValue<string>("Database")};" +
|
||||
$"uid={config.GetValue<string>("Username")};" +
|
||||
$"pwd={config.GetValue<string>("Password")}";
|
||||
var connectionString = $"host={config.Host};" +
|
||||
$"port={config.Port};" +
|
||||
$"database={config.Database};" +
|
||||
$"uid={config.Username};" +
|
||||
$"pwd={config.Password}";
|
||||
|
||||
string file = PathBuilder.File("storage", "backups", $"{dateTimeService.GetCurrentUnix()}-mysql.sql");
|
||||
|
||||
Logger.Info($"Saving it to: {file}");
|
||||
Logger.Info("Starting backup...");
|
||||
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
try
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
await using MySqlConnection conn = new MySqlConnection(connectionString);
|
||||
await using MySqlCommand cmd = new MySqlCommand();
|
||||
using MySqlBackup mb = new MySqlBackup(cmd);
|
||||
await using MySqlConnection conn = new MySqlConnection(connectionString);
|
||||
await using MySqlCommand cmd = new MySqlCommand();
|
||||
using MySqlBackup mb = new MySqlBackup(cmd);
|
||||
|
||||
cmd.Connection = conn;
|
||||
await conn.OpenAsync();
|
||||
mb.ExportToFile(file);
|
||||
await conn.CloseAsync();
|
||||
cmd.Connection = conn;
|
||||
await conn.OpenAsync();
|
||||
mb.ExportToFile(file);
|
||||
await conn.CloseAsync();
|
||||
|
||||
sw.Stop();
|
||||
Logger.Info($"Done. {sw.Elapsed.TotalSeconds}s");
|
||||
sw.Stop();
|
||||
Logger.Info($"Done. {sw.Elapsed.TotalSeconds}s");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Fatal("-----------------------------------------------");
|
||||
Logger.Fatal("Unable to create backup for moonlight database");
|
||||
Logger.Fatal("Moonlight will start anyways in 30 seconds");
|
||||
Logger.Fatal("-----------------------------------------------");
|
||||
Logger.Fatal(e);
|
||||
|
||||
Thread.Sleep(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Moonlight/App/Helpers/EggConverter.cs
Normal file
71
Moonlight/App/Helpers/EggConverter.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Text;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class EggConverter
|
||||
{
|
||||
public static Image Convert(string json)
|
||||
{
|
||||
var result = new Image();
|
||||
|
||||
var data = new ConfigurationBuilder().AddJsonStream(
|
||||
new MemoryStream(Encoding.ASCII.GetBytes(json))
|
||||
).Build();
|
||||
|
||||
result.Allocations = 1;
|
||||
result.Description = data.GetValue<string>("description") ?? "";
|
||||
result.Uuid = Guid.NewGuid();
|
||||
result.Startup = data.GetValue<string>("startup") ?? "";
|
||||
result.Name = data.GetValue<string>("name") ?? "Ptero Egg";
|
||||
|
||||
foreach (var variable in data.GetSection("variables").GetChildren())
|
||||
{
|
||||
result.Variables.Add(new()
|
||||
{
|
||||
Key = variable.GetValue<string>("env_variable") ?? "",
|
||||
DefaultValue = variable.GetValue<string>("default_value") ?? ""
|
||||
});
|
||||
}
|
||||
|
||||
var configData = data.GetSection("config");
|
||||
|
||||
result.ConfigFiles = configData.GetValue<string>("files") ?? "{}";
|
||||
|
||||
var dImagesData = JObject.Parse(json);
|
||||
var dImages = (JObject)dImagesData["docker_images"]!;
|
||||
|
||||
foreach (var dockerImage in dImages)
|
||||
{
|
||||
var di = new DockerImage()
|
||||
{
|
||||
Default = dockerImage.Key == dImages.Properties().Last().Name,
|
||||
Name = dockerImage.Value!.ToString()
|
||||
};
|
||||
|
||||
result.DockerImages.Add(di);
|
||||
}
|
||||
|
||||
var installSection = data.GetSection("scripts").GetSection("installation");
|
||||
|
||||
result.InstallEntrypoint = installSection.GetValue<string>("entrypoint") ?? "bash";
|
||||
result.InstallScript = installSection.GetValue<string>("script") ?? "";
|
||||
result.InstallDockerImage = installSection.GetValue<string>("container") ?? "";
|
||||
|
||||
var rawJson = configData.GetValue<string>("startup");
|
||||
|
||||
var startupData = new ConfigurationBuilder().AddJsonStream(
|
||||
new MemoryStream(Encoding.ASCII.GetBytes(rawJson!))
|
||||
).Build();
|
||||
|
||||
result.StartupDetection = startupData.GetValue<string>("done", "") ?? "";
|
||||
result.StopCommand = configData.GetValue<string>("stop") ?? "";
|
||||
|
||||
result.TagsJson = "[]";
|
||||
result.BackgroundImageUrl = "";
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Logging.Net;
|
||||
using Renci.SshNet;
|
||||
using Renci.SshNet;
|
||||
using ConnectionInfo = Renci.SshNet.ConnectionInfo;
|
||||
|
||||
namespace Moonlight.App.Helpers.Files;
|
||||
|
||||
@@ -111,7 +111,7 @@ public class WingsFileAccess : FileAccess
|
||||
request.AddParameter("name", "files");
|
||||
request.AddParameter("filename", name);
|
||||
request.AddHeader("Content-Type", "multipart/form-data");
|
||||
request.AddHeader("Origin", ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl"));
|
||||
request.AddHeader("Origin", ConfigService.Get().Moonlight.AppUrl);
|
||||
request.AddFile("files", () =>
|
||||
{
|
||||
return new StreamProgressHelper(dataStream)
|
||||
|
||||
@@ -1,9 +1,36 @@
|
||||
using Moonlight.App.Services;
|
||||
using System.Text;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class Formatter
|
||||
{
|
||||
public static string ReplaceEnd(string input, string substringToReplace, string newSubstring)
|
||||
{
|
||||
int lastIndexOfSubstring = input.LastIndexOf(substringToReplace);
|
||||
if (lastIndexOfSubstring >= 0)
|
||||
{
|
||||
input = input.Remove(lastIndexOfSubstring, substringToReplace.Length).Insert(lastIndexOfSubstring, newSubstring);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
public static string ConvertCamelCaseToSpaces(string input)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (char.IsUpper(c))
|
||||
{
|
||||
output.Append(' ');
|
||||
}
|
||||
|
||||
output.Append(c);
|
||||
}
|
||||
|
||||
return output.ToString().Trim();
|
||||
}
|
||||
public static string FormatUptime(double uptime)
|
||||
{
|
||||
TimeSpan t = TimeSpan.FromMilliseconds(uptime);
|
||||
@@ -18,6 +45,18 @@ public static class Formatter
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatUptime(TimeSpan t)
|
||||
{
|
||||
if (t.Days > 0)
|
||||
{
|
||||
return $"{t.Days}d {t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
}
|
||||
|
||||
private static double Round(this double d, int decimals)
|
||||
{
|
||||
return Math.Round(d, decimals);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Logging.Net;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
|
||||
171
Moonlight/App/Helpers/Logger.cs
Normal file
171
Moonlight/App/Helpers/Logger.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Moonlight.App.Database;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Files;
|
||||
using Serilog;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class Logger
|
||||
{
|
||||
// The private static instance of the config service, because we have no di here
|
||||
private static ConfigService ConfigService = new(new StorageService());
|
||||
|
||||
#region String method calls
|
||||
public static void Verbose(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
|
||||
public static void Info(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
|
||||
public static void Debug(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
|
||||
public static void Error(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
|
||||
public static void Warn(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
|
||||
public static void Fatal(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal("{Message}", message);
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Exception method calls
|
||||
public static void Verbose(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
|
||||
public static void Info(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
|
||||
public static void Debug(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
|
||||
public static void Error(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
|
||||
public static void Warn(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
|
||||
public static void Fatal(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal(exception, "");
|
||||
|
||||
if(channel == "security")
|
||||
LogSecurityInDb(exception);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static string GetNameOfCallingClass(int skipFrames = 4)
|
||||
{
|
||||
string fullName;
|
||||
Type declaringType;
|
||||
|
||||
do
|
||||
{
|
||||
MethodBase method = new StackFrame(skipFrames, false).GetMethod();
|
||||
declaringType = method.DeclaringType;
|
||||
if (declaringType == null)
|
||||
{
|
||||
return method.Name;
|
||||
}
|
||||
skipFrames++;
|
||||
if (declaringType.Name.Contains("<"))
|
||||
fullName = declaringType.ReflectedType.Name;
|
||||
else
|
||||
fullName = declaringType.Name;
|
||||
}
|
||||
while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase) | fullName.Contains("Logger"));
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
|
||||
private static void LogSecurityInDb(Exception exception)
|
||||
{
|
||||
LogSecurityInDb(exception.ToStringDemystified());
|
||||
}
|
||||
private static void LogSecurityInDb(string text)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var dataContext = new DataContext(ConfigService);
|
||||
|
||||
dataContext.SecurityLogs.Add(new()
|
||||
{
|
||||
Text = text
|
||||
});
|
||||
|
||||
dataContext.SaveChanges();
|
||||
dataContext.Dispose();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Logging.Net;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Logging.Net;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class ParseHelper
|
||||
{
|
||||
|
||||
51
Moonlight/App/Helpers/PropBinder.cs
Normal file
51
Moonlight/App/Helpers/PropBinder.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class PropBinder
|
||||
{
|
||||
private PropertyInfo PropertyInfo;
|
||||
private object DataObject;
|
||||
|
||||
public PropBinder(PropertyInfo propertyInfo, object dataObject)
|
||||
{
|
||||
PropertyInfo = propertyInfo;
|
||||
DataObject = dataObject;
|
||||
}
|
||||
|
||||
public string StringValue
|
||||
{
|
||||
get => (string)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public int IntValue
|
||||
{
|
||||
get => (int)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public long LongValue
|
||||
{
|
||||
get => (long)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public bool BoolValue
|
||||
{
|
||||
get => (bool)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public DateTime DateTimeValue
|
||||
{
|
||||
get => (DateTime)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public double DoubleValue
|
||||
{
|
||||
get => (double)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
}
|
||||
66
Moonlight/App/Helpers/Retry.cs
Normal file
66
Moonlight/App/Helpers/Retry.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class Retry
|
||||
{
|
||||
private List<Type> RetryExceptionTypes;
|
||||
private List<Func<Exception, bool>> RetryFilters;
|
||||
private int RetryTimes = 1;
|
||||
|
||||
public Retry()
|
||||
{
|
||||
RetryExceptionTypes = new();
|
||||
RetryFilters = new();
|
||||
}
|
||||
|
||||
public Retry Times(int times)
|
||||
{
|
||||
RetryTimes = times;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Retry At(Func<Exception, bool> filter)
|
||||
{
|
||||
RetryFilters.Add(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Retry At<T>()
|
||||
{
|
||||
RetryExceptionTypes.Add(typeof(T));
|
||||
return this;
|
||||
}
|
||||
|
||||
public async Task Call(Func<Task> method)
|
||||
{
|
||||
int triesLeft = RetryTimes;
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
await method.Invoke();
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if(triesLeft < 1) // Throw if no tries left
|
||||
throw;
|
||||
|
||||
if (RetryExceptionTypes.Any(x => x.FullName == e.GetType().FullName))
|
||||
{
|
||||
triesLeft--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RetryFilters.Any(x => x.Invoke(e)))
|
||||
{
|
||||
triesLeft--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Throw if not filtered -> unknown/unhandled
|
||||
throw;
|
||||
}
|
||||
} while (triesLeft >= 0);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.Helpers.Wings.Data;
|
||||
using Moonlight.App.Helpers.Wings.Enums;
|
||||
using Moonlight.App.Helpers.Wings.Events;
|
||||
@@ -243,6 +242,8 @@ public class WingsConsole : IDisposable
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(JsonReaderException){}
|
||||
catch(JsonSerializationException){}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!Disconnecting)
|
||||
|
||||
@@ -20,7 +20,7 @@ public class WingsConsoleHelper
|
||||
{
|
||||
ServerRepository = serverRepository;
|
||||
|
||||
AppUrl = configService.GetSection("Moonlight").GetValue<string>("AppUrl");
|
||||
AppUrl = configService.Get().Moonlight.AppUrl;
|
||||
}
|
||||
|
||||
public async Task ConnectWings(WingsConsole console, Server server)
|
||||
|
||||
@@ -15,7 +15,7 @@ public class WingsJwtHelper
|
||||
{
|
||||
ConfigService = configService;
|
||||
|
||||
AppUrl = ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl");
|
||||
AppUrl = ConfigService.Get().Moonlight.AppUrl;
|
||||
}
|
||||
|
||||
public string Generate(string secret, Action<Dictionary<string, string>> claimsAction)
|
||||
|
||||
@@ -25,7 +25,7 @@ public class AvatarController : Controller
|
||||
|
||||
try
|
||||
{
|
||||
var url = GravatarController.GetImageUrl(user.Email, 100);
|
||||
var url = GravatarController.GetImageUrl(user.Email.ToLower(), 100);
|
||||
|
||||
using var client = new HttpClient();
|
||||
var res = await client.GetByteArrayAsync(url);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
using Stripe;
|
||||
using Stripe.Checkout;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/moonlight/billing")]
|
||||
public class BillingController : Controller
|
||||
{
|
||||
private readonly IdentityService IdentityService;
|
||||
private readonly BillingService BillingService;
|
||||
|
||||
public BillingController(
|
||||
IdentityService identityService,
|
||||
BillingService billingService)
|
||||
{
|
||||
IdentityService = identityService;
|
||||
BillingService = billingService;
|
||||
}
|
||||
|
||||
[HttpGet("cancel")]
|
||||
public async Task<ActionResult> Cancel()
|
||||
{
|
||||
var user = IdentityService.User;
|
||||
|
||||
if (user == null)
|
||||
return Redirect("/login");
|
||||
|
||||
return Redirect("/profile/subscriptions/close");
|
||||
}
|
||||
|
||||
[HttpGet("success")]
|
||||
public async Task<ActionResult> Success()
|
||||
{
|
||||
var user = IdentityService.User;
|
||||
|
||||
if (user == null)
|
||||
return Redirect("/login");
|
||||
|
||||
await BillingService.CompleteCheckout(user);
|
||||
|
||||
return Redirect("/profile/subscriptions/close");
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,14 @@ public class DiscordBotController : Controller
|
||||
ServerService = serverService;
|
||||
|
||||
var config = configService
|
||||
.GetSection("Moonlight")
|
||||
.GetSection("DiscordBotApi");
|
||||
.Get()
|
||||
.Moonlight.DiscordBotApi;
|
||||
|
||||
Enable = config.GetValue<bool>("Enable");
|
||||
Enable = config.Enable;
|
||||
|
||||
if (Enable)
|
||||
{
|
||||
Token = config.GetValue<string>("Token");
|
||||
Token = config.Token;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class DiscordBotController : Controller
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
[HttpGet("{id}/servers/{uuid}")]
|
||||
[HttpGet("{id}/servers/{uuid}/details")]
|
||||
public async Task<ActionResult<ServerDetails>> GetServerDetails(ulong id, Guid uuid)
|
||||
{
|
||||
if (!await IsAuth(Request))
|
||||
@@ -124,6 +124,33 @@ public class DiscordBotController : Controller
|
||||
return await ServerService.GetDetails(server);
|
||||
}
|
||||
|
||||
[HttpGet("{id}/servers/{uuid}")]
|
||||
public async Task<ActionResult<ServerDetails>> GetServer(ulong id, Guid uuid)
|
||||
{
|
||||
if (!await IsAuth(Request))
|
||||
return StatusCode(403);
|
||||
|
||||
var user = await GetUserFromDiscordId(id);
|
||||
|
||||
if (user == null)
|
||||
return BadRequest();
|
||||
|
||||
var server = ServerRepository
|
||||
.Get()
|
||||
.Include(x => x.Owner)
|
||||
.Include(x => x.Image)
|
||||
.Include(x => x.Node)
|
||||
.FirstOrDefault(x => x.Owner.Id == user.Id && x.Uuid == uuid);
|
||||
|
||||
if (server == null)
|
||||
return NotFound();
|
||||
|
||||
server.Node.Token = "";
|
||||
server.Node.TokenId = "";
|
||||
|
||||
return Ok(server);
|
||||
}
|
||||
|
||||
private Task<User?> GetUserFromDiscordId(ulong discordId)
|
||||
{
|
||||
var user = UserRepository
|
||||
|
||||
@@ -2,145 +2,166 @@
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Database.Entities.Notification;
|
||||
using Moonlight.App.Models.Notifications;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Notifications;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Moonlight.Notifications;
|
||||
|
||||
public class ListenController : ControllerBase
|
||||
[ApiController]
|
||||
[Route("api/moonlight/notification/listen")]
|
||||
public class ListenController : Controller
|
||||
{
|
||||
internal WebSocket ws;
|
||||
private bool active = true;
|
||||
private bool isAuth = false;
|
||||
private WebSocket WebSocket;
|
||||
private NotificationClient Client;
|
||||
private CancellationTokenSource CancellationTokenSource = new();
|
||||
|
||||
private User? CurrentUser;
|
||||
|
||||
private readonly IdentityService IdentityService;
|
||||
private readonly NotificationRepository NotificationRepository;
|
||||
private readonly OneTimeJwtService OneTimeJwtService;
|
||||
private readonly NotificationClientService NotificationClientService;
|
||||
private readonly NotificationServerService NotificationServerService;
|
||||
private readonly Repository<NotificationClient> NotificationClientRepository;
|
||||
|
||||
public ListenController(IdentityService identityService,
|
||||
NotificationRepository notificationRepository,
|
||||
public ListenController(
|
||||
OneTimeJwtService oneTimeJwtService,
|
||||
NotificationClientService notificationClientService,
|
||||
NotificationServerService notificationServerService)
|
||||
NotificationServerService notificationServerService, Repository<NotificationClient> notificationClientRepository)
|
||||
{
|
||||
IdentityService = identityService;
|
||||
NotificationRepository = notificationRepository;
|
||||
OneTimeJwtService = oneTimeJwtService;
|
||||
NotificationClientService = notificationClientService;
|
||||
NotificationServerService = notificationServerService;
|
||||
NotificationClientRepository = notificationClientRepository;
|
||||
}
|
||||
|
||||
[Route("/api/moonlight/notifications/listen")]
|
||||
public async Task Get()
|
||||
public async Task<ActionResult> Get()
|
||||
{
|
||||
if (HttpContext.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
||||
ws = webSocket;
|
||||
await Echo();
|
||||
WebSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
||||
|
||||
await ProcessWebsocket();
|
||||
|
||||
return new EmptyResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||
return StatusCode(400);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Echo()
|
||||
private async Task ProcessWebsocket()
|
||||
{
|
||||
while (active)
|
||||
while (!CancellationTokenSource.Token.IsCancellationRequested && WebSocket.State == WebSocketState.Open)
|
||||
{
|
||||
byte[] bytes = new byte[1024 * 16];
|
||||
var asg = new ArraySegment<byte>(bytes);
|
||||
var res = await ws.ReceiveAsync(asg, CancellationToken.None);
|
||||
|
||||
var text = Encoding.UTF8.GetString(bytes).Trim('\0');
|
||||
|
||||
var obj = JsonConvert.DeserializeObject<BasicWSModel>(text);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(obj.Action))
|
||||
try
|
||||
{
|
||||
await HandleRequest(text, obj.Action);
|
||||
}
|
||||
byte[] buffer = new byte[1024 * 16];
|
||||
_ = await WebSocket.ReceiveAsync(buffer, CancellationTokenSource.Token);
|
||||
var text = Encoding.UTF8.GetString(buffer).Trim('\0');
|
||||
|
||||
active = ws.State == WebSocketState.Open;
|
||||
var basicWsModel = JsonConvert.DeserializeObject<BasicWSModel>(text) ?? new();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(basicWsModel.Action))
|
||||
{
|
||||
await HandleRequest(text, basicWsModel.Action);
|
||||
}
|
||||
|
||||
if (WebSocket.State != WebSocketState.Open)
|
||||
{
|
||||
CancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
catch (WebSocketException e)
|
||||
{
|
||||
CancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
await NotificationServerService.UnRegisterClient(Client);
|
||||
}
|
||||
|
||||
private async Task HandleRequest(string text, string action)
|
||||
{
|
||||
if (!isAuth && action == "login")
|
||||
await Login(text);
|
||||
else if (!isAuth)
|
||||
await ws.SendAsync(Encoding.UTF8.GetBytes("{\"error\": \"Unauthorised\"}"), WebSocketMessageType.Text,
|
||||
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||
else switch (action)
|
||||
if (CurrentUser == null && action != "login")
|
||||
{
|
||||
await Send("{\"error\": \"Unauthorised\"}");
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case "login":
|
||||
await Login(text);
|
||||
break;
|
||||
case "received":
|
||||
await Received(text);
|
||||
break;
|
||||
case "read":
|
||||
await Read(text);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Send(string text)
|
||||
{
|
||||
await WebSocket.SendAsync(
|
||||
Encoding.UTF8.GetBytes(text),
|
||||
WebSocketMessageType.Text,
|
||||
WebSocketMessageFlags.EndOfMessage, CancellationTokenSource.Token
|
||||
);
|
||||
}
|
||||
|
||||
private async Task Login(string json)
|
||||
{
|
||||
var jwt = JsonConvert.DeserializeObject<Login>(json).token;
|
||||
var loginModel = JsonConvert.DeserializeObject<Login>(json) ?? new();
|
||||
|
||||
var dict = await OneTimeJwtService.Validate(jwt);
|
||||
var dict = await OneTimeJwtService.Validate(loginModel.Token);
|
||||
|
||||
if (dict == null)
|
||||
{
|
||||
string error = "{\"status\":false}";
|
||||
var bytes = Encoding.UTF8.GetBytes(error);
|
||||
await ws.SendAsync(bytes, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||
await Send("{\"status\":false}");
|
||||
return;
|
||||
}
|
||||
|
||||
var _clientId = dict["clientId"];
|
||||
var clientId = int.Parse(_clientId);
|
||||
if (!int.TryParse(dict["clientId"], out int clientId))
|
||||
{
|
||||
await Send("{\"status\":false}");
|
||||
return;
|
||||
}
|
||||
|
||||
var client = NotificationRepository.GetClients().Include(x => x.User).First(x => x.Id == clientId);
|
||||
Client = NotificationClientRepository
|
||||
.Get()
|
||||
.Include(x => x.User)
|
||||
.First(x => x.Id == clientId);
|
||||
|
||||
Client = client;
|
||||
await InitWebsocket();
|
||||
CurrentUser = Client.User;
|
||||
|
||||
string success = "{\"status\":true}";
|
||||
var byt = Encoding.UTF8.GetBytes(success);
|
||||
await ws.SendAsync(byt, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||
}
|
||||
await NotificationServerService.RegisterClient(WebSocket, Client);
|
||||
|
||||
private async Task InitWebsocket()
|
||||
{
|
||||
NotificationClientService.listenController = this;
|
||||
NotificationClientService.WebsocketReady(Client);
|
||||
|
||||
isAuth = true;
|
||||
await Send("{\"status\":true}");
|
||||
}
|
||||
|
||||
private async Task Received(string json)
|
||||
{
|
||||
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
|
||||
var id = JsonConvert.DeserializeObject<NotificationById>(json).Notification;
|
||||
|
||||
//TODO: Implement ws notification received
|
||||
}
|
||||
|
||||
private async Task Read(string json)
|
||||
{
|
||||
var id = JsonConvert.DeserializeObject<NotificationById>(json).notification;
|
||||
var model = JsonConvert.DeserializeObject<NotificationById>(json) ?? new();
|
||||
|
||||
await NotificationServerService.SendAction(NotificationClientService.User,
|
||||
JsonConvert.SerializeObject(new NotificationById() {Action = "hide", notification = id}));
|
||||
await NotificationServerService.SendAction(
|
||||
CurrentUser!,
|
||||
JsonConvert.SerializeObject(
|
||||
new NotificationById()
|
||||
{
|
||||
Action = "hide", Notification = model.Notification
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class RegisterController : Controller
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<TokenRegister>> Register()
|
||||
{
|
||||
var user = await IdentityService.Get();
|
||||
var user = IdentityService.User;
|
||||
|
||||
if (user == null)
|
||||
return NotFound();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Logging.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class OAuth2Controller : Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentUser = await IdentityService.Get();
|
||||
var currentUser = IdentityService.User;
|
||||
|
||||
if (currentUser != null)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
using System.Text;
|
||||
using Logging.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Files;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
||||
|
||||
@@ -14,13 +8,10 @@ namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
||||
[Route("api/moonlight/resources")]
|
||||
public class ResourcesController : Controller
|
||||
{
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
private readonly BucketService BucketService;
|
||||
|
||||
public ResourcesController(SecurityLogService securityLogService,
|
||||
BucketService bucketService)
|
||||
public ResourcesController(BucketService bucketService)
|
||||
{
|
||||
SecurityLogService = securityLogService;
|
||||
BucketService = bucketService;
|
||||
}
|
||||
|
||||
@@ -29,10 +20,7 @@ public class ResourcesController : Controller
|
||||
{
|
||||
if (name.Contains(".."))
|
||||
{
|
||||
await SecurityLogService.Log(SecurityLogType.PathTransversal, x =>
|
||||
{
|
||||
x.Add<string>(name);
|
||||
});
|
||||
Logger.Warn($"Detected an attempted path transversal. Path: {name}", "security");
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
@@ -47,15 +35,32 @@ public class ResourcesController : Controller
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("background/{name}")]
|
||||
public async Task<ActionResult> GetBackground([FromRoute] string name)
|
||||
{
|
||||
if (name.Contains(".."))
|
||||
{
|
||||
Logger.Warn($"Detected an attempted path transversal. Path: {name}", "security");
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists(PathBuilder.File("storage", "resources", "public", "background", name)))
|
||||
{
|
||||
var fs = new FileStream(PathBuilder.File("storage", "resources", "public", "background", name), FileMode.Open);
|
||||
|
||||
return File(fs, MimeTypes.GetMimeType(name), name);
|
||||
}
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet("bucket/{bucket}/{name}")]
|
||||
public async Task<ActionResult> GetBucket([FromRoute] string bucket, [FromRoute] string name)
|
||||
{
|
||||
if (name.Contains(".."))
|
||||
{
|
||||
await SecurityLogService.Log(SecurityLogType.PathTransversal, x =>
|
||||
{
|
||||
x.Add<string>(name);
|
||||
});
|
||||
Logger.Warn($"Detected an attempted path transversal. Path: {name}", "security");
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using Logging.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Events;
|
||||
using Moonlight.App.Http.Requests.Daemon;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Remote;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Logging.Net;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
using Moonlight.App.Helpers;
|
||||
|
||||
namespace Moonlight.App.LogMigrator;
|
||||
|
||||
@@ -28,19 +27,39 @@ public class LogMigrator : ILogger
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Critical:
|
||||
Logger.Fatal($"[{Name}] {formatter(state, exception)}");
|
||||
Logger.Fatal(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Fatal(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
Logger.Warn($"[{Name}] {formatter(state, exception)}");
|
||||
Logger.Warn(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Warn(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
Logger.Debug($"[{Name}] {formatter(state, exception)}");
|
||||
Logger.Debug(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Debug(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
Logger.Error($"[{Name}] {formatter(state, exception)}");
|
||||
Logger.Error(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Error(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
Logger.Info($"[{Name}] {formatter(state, exception)}");
|
||||
Logger.Info(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Info(exception);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
71
Moonlight/App/LogMigrator/SentryDiagnosticsLogger.cs
Normal file
71
Moonlight/App/LogMigrator/SentryDiagnosticsLogger.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Moonlight.App.Helpers;
|
||||
using Sentry;
|
||||
using Sentry.Extensibility;
|
||||
|
||||
namespace Moonlight.App.LogMigrator;
|
||||
|
||||
public class SentryDiagnosticsLogger : IDiagnosticLogger
|
||||
{
|
||||
private readonly SentryLevel Level;
|
||||
|
||||
public SentryDiagnosticsLogger(SentryLevel level)
|
||||
{
|
||||
Level = level;
|
||||
}
|
||||
|
||||
public bool IsEnabled(SentryLevel level)
|
||||
{
|
||||
if ((int)level >= (int)Level)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Log(SentryLevel logLevel, string message, Exception? exception = null, params object?[] args)
|
||||
{
|
||||
switch (logLevel)
|
||||
{
|
||||
case SentryLevel.Debug:
|
||||
Logger.Debug(string.Format(message, args));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Debug(exception);
|
||||
|
||||
break;
|
||||
|
||||
case SentryLevel.Info:
|
||||
Logger.Info(string.Format(message, args));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Info(exception);
|
||||
|
||||
break;
|
||||
|
||||
case SentryLevel.Warning:
|
||||
Logger.Warn(string.Format(message, args));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Warn(exception);
|
||||
|
||||
break;
|
||||
|
||||
case SentryLevel.Error:
|
||||
Logger.Error(string.Format(message, args));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Error(exception);
|
||||
|
||||
break;
|
||||
|
||||
case SentryLevel.Fatal:
|
||||
Logger.Fatal(string.Format(message, args));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Fatal(exception);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Moonlight/App/Models/Forms/ServerImageDataModel.cs
Normal file
8
Moonlight/App/Models/Forms/ServerImageDataModel.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class ServerImageDataModel
|
||||
{
|
||||
public string OverrideStartup { get; set; }
|
||||
|
||||
public int DockerImageIndex { get; set; }
|
||||
}
|
||||
14
Moonlight/App/Models/Forms/ServerOverviewDataModel.cs
Normal file
14
Moonlight/App/Models/Forms/ServerOverviewDataModel.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class ServerOverviewDataModel
|
||||
{
|
||||
[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 owner")]
|
||||
public User Owner { get; set; }
|
||||
}
|
||||
15
Moonlight/App/Models/Forms/ServerResourcesDataModel.cs
Normal file
15
Moonlight/App/Models/Forms/ServerResourcesDataModel.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class ServerResourcesDataModel
|
||||
{
|
||||
[Required(ErrorMessage = "You need to specify the cpu cores")]
|
||||
public int Cpu { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "You need to specify the memory")]
|
||||
public long Memory { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "You need to specify the disk")]
|
||||
public long Disk { get; set; }
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
@@ -10,4 +11,8 @@ public class SubscriptionDataModel
|
||||
|
||||
[Required(ErrorMessage = "You need to enter a description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
public double Price { get; set; } = 0;
|
||||
public Currency Currency { get; set; } = Currency.USD;
|
||||
public int Duration { get; set; } = 30;
|
||||
}
|
||||
34
Moonlight/App/Models/Forms/UserEditDataModel.cs
Normal file
34
Moonlight/App/Models/Forms/UserEditDataModel.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Models.Misc;
|
||||
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class UserEditDataModel
|
||||
{
|
||||
[Required]
|
||||
public string FirstName { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string LastName { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string Email { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string Address { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string City { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string State { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
public string Country { get; set; } = "";
|
||||
|
||||
public bool Admin { get; set; }
|
||||
public bool TotpEnabled { get; set; }
|
||||
public ulong DiscordId { get; set; }
|
||||
public PermissionGroup? PermissionGroup { get; set; }
|
||||
}
|
||||
6
Moonlight/App/Models/Forms/UserPreferencesDataModel.cs
Normal file
6
Moonlight/App/Models/Forms/UserPreferencesDataModel.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Moonlight.App.Models.Forms;
|
||||
|
||||
public class UserPreferencesDataModel
|
||||
{
|
||||
public bool StreamerMode { get; set; } = false;
|
||||
}
|
||||
19
Moonlight/App/Models/Misc/ActiveNotificationClient.cs
Normal file
19
Moonlight/App/Models/Misc/ActiveNotificationClient.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Moonlight.App.Database.Entities.Notification;
|
||||
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class ActiveNotificationClient
|
||||
{
|
||||
public WebSocket WebSocket { get; set; }
|
||||
public NotificationClient Client { get; set; }
|
||||
|
||||
public async Task SendAction(string action)
|
||||
{
|
||||
await WebSocket.SendAsync(
|
||||
Encoding.UTF8.GetBytes(action),
|
||||
WebSocketMessageType.Text,
|
||||
WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public enum AuditLogType
|
||||
{
|
||||
Login,
|
||||
Register,
|
||||
ChangePassword,
|
||||
ChangePowerState,
|
||||
CreateBackup,
|
||||
RestoreBackup,
|
||||
DeleteBackup,
|
||||
DownloadBackup,
|
||||
CreateServer,
|
||||
ReinstallServer,
|
||||
CancelSubscription,
|
||||
ApplySubscriptionCode,
|
||||
EnableTotp,
|
||||
DisableTotp,
|
||||
AddDomainRecord,
|
||||
UpdateDomainRecord,
|
||||
DeleteDomainRecord,
|
||||
PasswordReset,
|
||||
CleanupEnabled,
|
||||
CleanupDisabled,
|
||||
CleanupTriggered,
|
||||
PasswordChange,
|
||||
}
|
||||
7
Moonlight/App/Models/Misc/Currency.cs
Normal file
7
Moonlight/App/Models/Misc/Currency.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public enum Currency
|
||||
{
|
||||
USD = 1,
|
||||
EUR = 2
|
||||
}
|
||||
19
Moonlight/App/Models/Misc/HealthCheck.cs
Normal file
19
Moonlight/App/Models/Misc/HealthCheck.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class HealthCheck
|
||||
{
|
||||
public string Status { get; set; }
|
||||
public TimeSpan TotalDuration { get; set; }
|
||||
public Dictionary<string, HealthCheckEntry> Entries { get; set; } = new();
|
||||
|
||||
public class HealthCheckEntry
|
||||
{
|
||||
public Dictionary<string, string> Data { get; set; } = new();
|
||||
public string Description { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public string Status { get; set; }
|
||||
public List<string> Tags { get; set; } = new();
|
||||
}
|
||||
}
|
||||
9
Moonlight/App/Models/Misc/MailTemplate.cs
Normal file
9
Moonlight/App/Models/Misc/MailTemplate.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Moonlight.App.Helpers.Files;
|
||||
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class MailTemplate // This is just for the blazor table at /admin/system/mail
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public FileData File { get; set; }
|
||||
}
|
||||
8
Moonlight/App/Models/Misc/MalwareScanResult.cs
Normal file
8
Moonlight/App/Models/Misc/MalwareScanResult.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class MalwareScanResult
|
||||
{
|
||||
public string Title { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string Author { get; set; } = "";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public enum SecurityLogType
|
||||
{
|
||||
ManipulatedJwt,
|
||||
PathTransversal,
|
||||
SftpBruteForce,
|
||||
LoginFail
|
||||
}
|
||||
7
Moonlight/App/Models/Misc/ServerGroup.cs
Normal file
7
Moonlight/App/Models/Misc/ServerGroup.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class ServerGroup
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public List<string> Servers { get; set; } = new();
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Services.Interop;
|
||||
|
||||
namespace Moonlight.App.Models.Misc;
|
||||
|
||||
public class Session
|
||||
{
|
||||
public string Ip { get; set; } = "N/A";
|
||||
public string Url { get; set; } = "N/A";
|
||||
public string Device { get; set; } = "N/A";
|
||||
public User? User { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public NavigationManager Navigation { get; set; }
|
||||
public AlertService AlertService { get; set; }
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
namespace Moonlight.App.Models.Notifications;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Models.Notifications;
|
||||
|
||||
public class Login : BasicWSModel
|
||||
{
|
||||
public string token { get; set; }
|
||||
[JsonProperty("token")] public string Token { get; set; } = "";
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
namespace Moonlight.App.Models.Notifications;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Models.Notifications;
|
||||
|
||||
public class NotificationById : BasicWSModel
|
||||
{
|
||||
public int notification { get; set; }
|
||||
[JsonProperty("notification")]
|
||||
public int Notification { get; set; }
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Text;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Helpers;
|
||||
@@ -87,6 +86,13 @@ public class DiscordOAuth2Provider : OAuth2Provider
|
||||
|
||||
var email = getData.GetValue<string>("email");
|
||||
var id = getData.GetValue<ulong>("id");
|
||||
var verified = getData.GetValue<bool>("verified");
|
||||
|
||||
if (!verified)
|
||||
{
|
||||
Logger.Warn("A user tried to use an unverified discord account to login", "security");
|
||||
throw new DisplayException("You can only use verified discord accounts for oauth signin");
|
||||
}
|
||||
|
||||
// Handle data
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Text;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.ApiClients.Google.Requests;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
|
||||
10
Moonlight/App/Perms/Permission.cs
Normal file
10
Moonlight/App/Perms/Permission.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Moonlight.App.Perms;
|
||||
|
||||
public class Permission
|
||||
{
|
||||
public int Index { get; set; } = 0;
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
public static implicit operator int(Permission permission) => permission.Index;
|
||||
}
|
||||
11
Moonlight/App/Perms/PermissionRequired.cs
Normal file
11
Moonlight/App/Perms/PermissionRequired.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Moonlight.App.Perms;
|
||||
|
||||
public class PermissionRequired : Attribute
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public PermissionRequired(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user