diff --git a/Moonlight/App/Services/Interop/AlertService.cs b/Moonlight/App/Services/Interop/AlertService.cs index d03d4ef9..7e6bcb25 100644 --- a/Moonlight/App/Services/Interop/AlertService.cs +++ b/Moonlight/App/Services/Interop/AlertService.cs @@ -5,10 +5,12 @@ namespace Moonlight.App.Services.Interop; public class AlertService { private readonly SweetAlertService SweetAlertService; + private readonly SmartTranslateService SmartTranslateService; - public AlertService(SweetAlertService service) + public AlertService(SweetAlertService service, SmartTranslateService smartTranslateService) { SweetAlertService = service; + SmartTranslateService = smartTranslateService; } public async Task Info(string title, string desciption) @@ -21,6 +23,11 @@ public class AlertService }); } + public async Task Info(string desciption) + { + await Info("", desciption); + } + public async Task Success(string title, string desciption) { await SweetAlertService.FireAsync(new SweetAlertOptions() @@ -31,6 +38,11 @@ public class AlertService }); } + public async Task Success(string desciption) + { + await Success("", desciption); + } + public async Task Warning(string title, string desciption) { await SweetAlertService.FireAsync(new SweetAlertOptions() @@ -41,6 +53,11 @@ public class AlertService }); } + public async Task Warning(string desciption) + { + await Warning("", desciption); + } + public async Task Error(string title, string desciption) { await SweetAlertService.FireAsync(new SweetAlertOptions() @@ -51,6 +68,11 @@ public class AlertService }); } + public async Task Error(string desciption) + { + await Error("", desciption); + } + public async Task YesNo(string title, string desciption, string yesText, string noText) { var result = await SweetAlertService.FireAsync(new SweetAlertOptions() @@ -79,4 +101,27 @@ public class AlertService return result.Value; } + + public async Task ConfirmMath() + { + var r = new Random(); + var i1 = r.Next(5, 15); + var i2 = r.Next(5, 15); + + var input = await Text( + SmartTranslateService.Translate("Confirm"), + SmartTranslateService.Translate($"{i1} + {i2} ="), + "" + ); + + if (int.TryParse(input, out int i)) + { + if (i == i1 + i2) + { + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/Moonlight/App/Services/Interop/ClipboardService.cs b/Moonlight/App/Services/Interop/ClipboardService.cs index 79fa4202..a7c806c9 100644 --- a/Moonlight/App/Services/Interop/ClipboardService.cs +++ b/Moonlight/App/Services/Interop/ClipboardService.cs @@ -15,4 +15,9 @@ public class ClipboardService { await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data); } + public async Task Copy(string data) + { + await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data); + } + } \ No newline at end of file diff --git a/Moonlight/App/Services/SubscriptionService.cs b/Moonlight/App/Services/SubscriptionService.cs index 9d35fe4b..de23692a 100644 --- a/Moonlight/App/Services/SubscriptionService.cs +++ b/Moonlight/App/Services/SubscriptionService.cs @@ -78,55 +78,45 @@ public class SubscriptionService await OneTimeJwtService.Revoke(code); } + public async Task Cancel() + { + if (await GetCurrent() != null) + { + var user = await GetCurrentUser(); + + user.CurrentSubscription = null; + + UserRepository.Update(user); + } + } + public async Task GetLimit(string identifier) { - var configSection = ConfigService.GetSection("Moonlight").GetSection("Subscriptions"); - - var defaultLimits = configSection.GetValue("DefaultLimits"); - var subscription = await GetCurrent(); if (subscription == null) { - if (defaultLimits != null) - { - var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier); - - if (foundDefault != null) - return foundDefault; - } - return new() { Identifier = identifier, Amount = 0 }; } - else + + var subscriptionLimits = + JsonConvert.DeserializeObject(subscription.LimitsJson) + ?? Array.Empty(); + + var foundLimit = subscriptionLimits.FirstOrDefault(x => x.Identifier == identifier); + + if (foundLimit != null) + return foundLimit; + + return new() { - var subscriptionLimits = - JsonConvert.DeserializeObject(subscription.LimitsJson) - ?? Array.Empty(); - - var foundLimit = subscriptionLimits.FirstOrDefault(x => x.Identifier == identifier); - - if (foundLimit != null) - return foundLimit; - - if (defaultLimits != null) - { - var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier); - - if (foundDefault != null) - return foundDefault; - } - - return new() - { - Identifier = identifier, - Amount = 0 - }; - } + Identifier = identifier, + Amount = 0 + }; } private async Task GetCurrentUser() diff --git a/Moonlight/Shared/Views/Admin/Subscriptions/Index.razor b/Moonlight/Shared/Views/Admin/Subscriptions/Index.razor index 83c20654..e7182f6a 100644 --- a/Moonlight/Shared/Views/Admin/Subscriptions/Index.razor +++ b/Moonlight/Shared/Views/Admin/Subscriptions/Index.razor @@ -3,10 +3,15 @@ @using Moonlight.App.Database.Entities @using Moonlight.App.Repositories @using BlazorTable +@using Moonlight.App.Services.Interop @inject SmartTranslateService SmartTranslateService @inject SubscriptionRepository SubscriptionRepository +@inject SubscriptionAdminService SubscriptionAdminService +@inject AlertService AlertService +@inject ClipboardService ClipboardService +
@@ -36,9 +41,16 @@ - + @@ -66,7 +78,24 @@ private async Task Delete(Subscription subscription) { SubscriptionRepository.Delete(subscription); - + await LazyLoader.Reload(); } + + private async Task GenerateCode(Subscription subscription) + { + var durationText = await AlertService.Text( + SmartTranslateService.Translate("Duration"), + SmartTranslateService.Translate("Enter duration of subscription"), + "30" + ); + + if (int.TryParse(durationText, out int duration)) + { + var code = await SubscriptionAdminService.GenerateCode(subscription, duration); + + await ClipboardService.Copy(code); + await AlertService.Success(SmartTranslateService.Translate("Copied code to clipboard")); + } + } } \ No newline at end of file diff --git a/Moonlight/Shared/Views/Profile/Subscriptions.razor b/Moonlight/Shared/Views/Profile/Subscriptions.razor new file mode 100644 index 00000000..c8382775 --- /dev/null +++ b/Moonlight/Shared/Views/Profile/Subscriptions.razor @@ -0,0 +1,112 @@ +@page "/profile/subscriptions" + +@using Moonlight.Shared.Components.Navigations +@using Moonlight.App.Services +@using Moonlight.App.Database.Entities +@using Moonlight.App.Helpers +@using Moonlight.App.Services.Interop + +@inject ConfigService ConfigService +@inject AlertService AlertService +@inject SubscriptionService SubscriptionService +@inject SmartTranslateService SmartTranslateService + + + +
+
+
+ Subscription +
+
+
+ + @if (Subscription == null) + { + var config = ConfigService + .GetSection("Moonlight") + .GetSection("Subscriptions") + .GetSection("Sellpass"); + + var enableSellpass = config.GetValue("Enable"); + var url = config.GetValue("Url"); + +

+
+ + + +
+

+ + if (enableSellpass) + { + + } + } + else + { + var d = User.SubscriptionSince.AddDays(User.SubscriptionDuration).ToUniversalTime(); + +

+ Active until @(Formatter.FormatDateOnly(d)) +

+

+ Current subscription: @(Subscription.Name) +

+

+ @(Subscription.Description) +

+

+ We will send you a notification upon subscription expiration +

+
+ + +
+ } +
+
+
+
+
+ +@code +{ + [CascadingParameter] + public User User { get; set; } + + private Subscription? Subscription; + private LazyLoader LazyLoader; + + private string Code = ""; + + private async Task Load(LazyLoader arg) + { + Subscription = await SubscriptionService.GetCurrent(); + } + + private async Task Cancel() + { + if (await AlertService.ConfirmMath()) + { + await SubscriptionService.Cancel(); + await LazyLoader.Reload(); + } + } + + private async Task OnSubmit() + { + await SubscriptionService.ApplyCode(Code); + Code = ""; + await LazyLoader.Reload(); + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Views/Servers/New.razor b/Moonlight/Shared/Views/Servers/Create.razor similarity index 78% rename from Moonlight/Shared/Views/Servers/New.razor rename to Moonlight/Shared/Views/Servers/Create.razor index 5fb01f0e..85ec9d91 100644 --- a/Moonlight/Shared/Views/Servers/New.razor +++ b/Moonlight/Shared/Views/Servers/Create.razor @@ -1,14 +1,20 @@ -@page "/servers/new" +@page "/servers/create" @using Moonlight.App.Services @using Moonlight.App.Database.Entities @using Moonlight.App.Models.Forms @using Moonlight.App.Models.Misc @using Moonlight.App.Repositories +@using Moonlight.App.Repositories.Servers +@using Microsoft.EntityFrameworkCore +@using Moonlight.App.Exceptions @inject SubscriptionService SubscriptionService @inject ImageRepository ImageRepository @inject SmartTranslateService SmartTranslateService @inject SmartDeployService SmartDeployService +@inject ServerRepository ServerRepository +@inject NavigationManager NavigationManager +@inject ServerService ServerService @if (DeployNode == null) @@ -133,6 +139,9 @@ @code { + [CascadingParameter] + public User User { get; set; } + private Node? DeployNode; private Subscription? Subscription; @@ -163,12 +172,55 @@ if (limit.Amount > 0) { - Images.Add(image, limit); + var serversCount = ServerRepository + .Get() + .Include(x => x.Owner) + .Include(x => x.Image) + .Where(x => x.Owner.Id == User.Id) + .Count(x => x.Image.Id == image.Id); + + if(serversCount < limit.Amount) + Images.Add(image, limit); } } } private async Task OnValidSubmit() { + var limit = await SubscriptionService.GetLimit("image." + Model.Image.Id); + + if (limit.Amount > 0) + { + var serversCount = ServerRepository + .Get() + .Include(x => x.Owner) + .Include(x => x.Image) + .Where(x => x.Owner.Id == User.Id) + .Count(x => x.Image.Id == Model.Image.Id); + + if (serversCount < limit.Amount) + { + if(int.TryParse(limit.ReadValue("cpu"), out int cpu) && + int.TryParse(limit.ReadValue("memory"), out int memory) && + int.TryParse(limit.ReadValue("disk"), out int disk)) + { + var server = await ServerService.Create( + Model.Name, + cpu, + memory, + disk, + User, + Model.Image, + DeployNode + ); + + NavigationManager.NavigateTo($"/server/{server.Uuid}"); + } + else + { + throw new DisplayException("Limits cannot be parsed"); + } + } + } } } \ No newline at end of file diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index bcb775a2..23a0c02f 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -475,3 +475,19 @@ No node found;No node found No node found to deploy to found;No node found to deploy to found You need to specify a server image;You need to specify a server image CPU;CPU +Compress;Compress +Decompress;Decompress +Cleanup exception;Cleanup exception +Error creating server on wings;Error creating server on wings +Enter code;Enter code +Create code;Create code +Duration;Duration +Enter duration of subscription;Enter duration of subscription +Copied code to clipboard;Copied code to clipboard +Current subscription;Current subscription +7 + 7 =;7 + 7 = +1 + 8 =;1 + 8 = +8 + 4 =;8 + 4 = +8 + 1 =;8 + 1 = +1 + 1 =;1 + 1 = +6 + 6 =;6 + 6 = diff --git a/Moonlight/wwwroot/assets/media/svg/subscription.svg b/Moonlight/wwwroot/assets/media/svg/subscription.svg new file mode 100644 index 00000000..6022690d --- /dev/null +++ b/Moonlight/wwwroot/assets/media/svg/subscription.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file