Merge branch 'main' into Register

This commit is contained in:
Daniel Balk
2023-04-12 18:02:31 +02:00
committed by GitHub
9 changed files with 128 additions and 112 deletions

View File

@@ -58,7 +58,7 @@ public class OAuth2Controller : Controller
} }
else else
{ {
token = await UserService.GenerateToken(user); token = await UserService.GenerateToken(user, true);
} }
Response.Cookies.Append("token", token, new () Response.Cookies.Append("token", token, new ()
@@ -116,7 +116,7 @@ public class OAuth2Controller : Controller
} }
else else
{ {
token = await UserService.GenerateToken(user); token = await UserService.GenerateToken(user, true);
} }
Response.Cookies.Append("token", token, new () Response.Cookies.Append("token", token, new ()

View File

@@ -195,7 +195,7 @@ public class ServerService
ServerRepository.Update(serverData); ServerRepository.Update(serverData);
await MessageService.Emit("wings.backups.delete", backup); await MessageService.Emit("wings.backups.delete", backup);
await AuditLogService.Log(AuditLogType.DeleteBackup, await AuditLogService.Log(AuditLogType.DeleteBackup,
x => x =>
{ {
@@ -213,7 +213,7 @@ public class ServerService
claims.Add("server_uuid", server.Uuid.ToString()); claims.Add("server_uuid", server.Uuid.ToString());
claims.Add("backup_uuid", serverBackup.Uuid.ToString()); claims.Add("backup_uuid", serverBackup.Uuid.ToString());
}); });
await AuditLogService.Log(AuditLogType.DownloadBackup, await AuditLogService.Log(AuditLogType.DownloadBackup,
x => x =>
{ {
@@ -221,7 +221,10 @@ public class ServerService
x.Add<ServerBackup>(serverBackup.Uuid); x.Add<ServerBackup>(serverBackup.Uuid);
}); });
return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}"; if (server.Node.Ssl)
return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}";
else
return $"http://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}";
} }
public Task<FileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url public Task<FileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url
@@ -240,7 +243,7 @@ public class ServerService
} }
public async Task<Server> Create(string name, int cpu, long memory, long disk, User u, Image i, Node? n = null, public async Task<Server> Create(string name, int cpu, long memory, long disk, User u, Image i, Node? n = null,
Action<Server>? modifyDetails = null) Action<Server>? modifyDetails = null, int allocations = 1)
{ {
var user = UserRepository var user = UserRepository
.Get() .Get()
@@ -264,22 +267,27 @@ public class ServerService
else else
node = n; node = n;
NodeAllocation freeAllo; NodeAllocation[] freeAllocations;
try try
{ {
freeAllo = node.Allocations.First(a => !ServerRepository.Get() freeAllocations = node.Allocations
.SelectMany(s => s.Allocations) .Where(a => !ServerRepository.Get()
.Any(b => b.Id == a.Id)); // Thank you ChatGPT <3 .SelectMany(s => s.Allocations)
.Any(b => b.Id == a.Id))
.Take(allocations).ToArray();
} }
catch (Exception) catch (Exception)
{ {
throw new DisplayException("No allocation found"); throw new DisplayException("No allocation found");
} }
if (freeAllo == null) if (!freeAllocations.Any())
throw new DisplayException("No allocation found"); throw new DisplayException("No allocation found");
if (freeAllocations.Length != allocations)
throw new DisplayException("Not enough allocations found");
var server = new Server() var server = new Server()
{ {
Cpu = cpu, Cpu = cpu,
@@ -290,11 +298,8 @@ public class ServerService
Owner = user, Owner = user,
Node = node, Node = node,
Uuid = Guid.NewGuid(), Uuid = Guid.NewGuid(),
MainAllocation = freeAllo, MainAllocation = freeAllocations.First(),
Allocations = new() Allocations = freeAllocations.ToList(),
{
freeAllo
},
Backups = new(), Backups = new(),
OverrideStartup = "", OverrideStartup = "",
DockerImageIndex = image.DockerImages.FindIndex(x => x.Default) DockerImageIndex = image.DockerImages.FindIndex(x => x.Default)
@@ -322,10 +327,7 @@ public class ServerService
StartOnCompletion = false StartOnCompletion = false
}); });
await AuditLogService.Log(AuditLogType.CreateServer, x => await AuditLogService.Log(AuditLogType.CreateServer, x => { x.Add<Server>(newServerData.Uuid); });
{
x.Add<Server>(newServerData.Uuid);
});
return newServerData; return newServerData;
} }
@@ -333,7 +335,7 @@ public class ServerService
{ {
await ErrorLogService.Log(e, x => await ErrorLogService.Log(e, x =>
{ {
x.Add<Server>(newServerData.Uuid); x.Add<Server>(newServerData.Uuid);
x.Add<Node>(node.Id); x.Add<Node>(node.Id);
}); });
@@ -349,10 +351,7 @@ public class ServerService
await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/reinstall", null); await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/reinstall", null);
await AuditLogService.Log(AuditLogType.ReinstallServer, x => await AuditLogService.Log(AuditLogType.ReinstallServer, x => { x.Add<Server>(server.Uuid); });
{
x.Add<Server>(server.Uuid);
});
} }
public async Task<Server> SftpServerLogin(int serverId, int id, string password) public async Task<Server> SftpServerLogin(int serverId, int id, string password)
@@ -361,10 +360,7 @@ public class ServerService
if (server == null) if (server == null)
{ {
await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, x => await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, x => { x.Add<int>(id); });
{
x.Add<int>(id);
});
throw new Exception("Server not found"); throw new Exception("Server not found");
} }
@@ -393,7 +389,7 @@ public class ServerService
var server = EnsureNodeData(s); var server = EnsureNodeData(s);
await WingsApiHelper.Delete(server.Node, $"api/servers/{server.Uuid}", null); await WingsApiHelper.Delete(server.Node, $"api/servers/{server.Uuid}", null);
ServerRepository.Delete(s); ServerRepository.Delete(s);
} }

View File

@@ -18,6 +18,7 @@ public class UserService
private readonly AuditLogService AuditLogService; private readonly AuditLogService AuditLogService;
private readonly MailService MailService; private readonly MailService MailService;
private readonly IdentityService IdentityService; private readonly IdentityService IdentityService;
private readonly IpLocateService IpLocateService;
private readonly string JwtSecret; private readonly string JwtSecret;
@@ -28,7 +29,7 @@ public class UserService
SecurityLogService securityLogService, SecurityLogService securityLogService,
AuditLogService auditLogService, AuditLogService auditLogService,
MailService mailService, MailService mailService,
IdentityService identityService) IdentityService identityService, IpLocateService ipLocateService)
{ {
UserRepository = userRepository; UserRepository = userRepository;
TotpService = totpService; TotpService = totpService;
@@ -36,6 +37,7 @@ public class UserService
AuditLogService = auditLogService; AuditLogService = auditLogService;
MailService = mailService; MailService = mailService;
IdentityService = identityService; IdentityService = identityService;
IpLocateService = ipLocateService;
JwtSecret = configService JwtSecret = configService
.GetSection("Moonlight") .GetSection("Moonlight")
@@ -77,6 +79,7 @@ public class UserService
}); });
await MailService.SendMail(user!, "register", values => {}); await MailService.SendMail(user!, "register", values => {});
await AuditLogService.Log(AuditLogType.Register, x => await AuditLogService.Log(AuditLogType.Register, x =>
{ {
x.Add<User>(user.Email); x.Add<User>(user.Email);
@@ -177,11 +180,13 @@ public class UserService
} }
else else
{ {
var location = await IpLocateService.GetLocation();
await MailService.SendMail(user!, "passwordChange", values => await MailService.SendMail(user!, "passwordChange", values =>
{ {
values.Add("Ip", IdentityService.GetIp()); values.Add("Ip", IdentityService.GetIp());
values.Add("Device", IdentityService.GetDevice()); values.Add("Device", IdentityService.GetDevice());
values.Add("Location", "In your walls"); values.Add("Location", location);
}); });
await AuditLogService.Log(AuditLogType.ChangePassword, x => await AuditLogService.Log(AuditLogType.ChangePassword, x =>
@@ -201,6 +206,7 @@ public class UserService
{ {
x.Add<int>(id); x.Add<int>(id);
}); });
throw new Exception("Invalid username"); throw new Exception("Invalid username");
} }
@@ -223,12 +229,17 @@ public class UserService
public async Task<string> GenerateToken(User user, bool sendMail = false) public async Task<string> GenerateToken(User user, bool sendMail = false)
{ {
await MailService.SendMail(user!, "login", values => var location = await IpLocateService.GetLocation();
if (sendMail)
{ {
values.Add("Ip", IdentityService.GetIp()); await MailService.SendMail(user!, "login", values =>
values.Add("Device", IdentityService.GetDevice()); {
values.Add("Location", "In your walls"); values.Add("Ip", IdentityService.GetIp());
}); values.Add("Device", IdentityService.GetDevice());
values.Add("Location", location);
});
}
var token = JwtBuilder.Create() var token = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm()) .WithAlgorithm(new HMACSHA256Algorithm())
@@ -257,11 +268,13 @@ public class UserService
await AuditLogService.Log(AuditLogType.PasswordReset, x => {}); await AuditLogService.Log(AuditLogType.PasswordReset, x => {});
var location = await IpLocateService.GetLocation();
await MailService.SendMail(user, "passwordReset", values => await MailService.SendMail(user, "passwordReset", values =>
{ {
values.Add("Ip", IdentityService.GetIp()); values.Add("Ip", IdentityService.GetIp());
values.Add("Device", IdentityService.GetDevice()); values.Add("Device", IdentityService.GetDevice());
values.Add("Location", "In your walls"); values.Add("Location", location);
values.Add("Password", newPassword); values.Add("Password", newPassword);
}); });
} }

View File

@@ -7,13 +7,35 @@
@inject AlertService AlertService @inject AlertService AlertService
@inject SmartTranslateService SmartTranslateService @inject SmartTranslateService SmartTranslateService
@ChildContent @if (Crashed)
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
<TL>Ooops. This page is crashed</TL>
</span>
</div>
<div class="text-center">
<TL>This page is crashed. The error has been reported to the moonlight team. Meanwhile you can try reloading the page</TL>
</div>
</div>
</div>
</div>
}
else
{
@ChildContent
}
@code @code
{ {
private bool Crashed = false;
protected override async Task OnErrorAsync(Exception exception) protected override async Task OnErrorAsync(Exception exception)
{ {
Logger.Debug(exception); Logger.Warn(exception);
if (exception is DisplayException displayException) if (exception is DisplayException displayException)
{ {
@@ -49,7 +71,8 @@
} }
else else
{ {
throw exception; Crashed = true;
await InvokeAsync(StateHasChanged);
} }
} }
} }

View File

@@ -59,57 +59,55 @@
<div id="kt_app_content" class="app-content flex-column-fluid"> <div id="kt_app_content" class="app-content flex-column-fluid">
<div id="kt_app_content_container" class="app-container container-fluid"> <div id="kt_app_content_container" class="app-container container-fluid">
<div class="mt-10"> <div class="mt-10">
<PageErrorBoundary> <SoftErrorBoundary>
<SoftErrorBoundary> @if (uri.LocalPath != "/login" &&
@if (uri.LocalPath != "/login" && uri.LocalPath != "/passwordreset" &&
uri.LocalPath != "/passwordreset" && uri.LocalPath != "/register")
uri.LocalPath != "/register") {
if (User == null)
{ {
if (User == null) <Login></Login>
{
<Login></Login>
}
else
{
if (User.Status == UserStatus.Banned)
{
<BannedAlert></BannedAlert>
}
else if (User.Status == UserStatus.Disabled)
{
<DisabledAlert></DisabledAlert>
}
else if (User.Status == UserStatus.PasswordPending)
{
<PasswordChangeView></PasswordChangeView>
}
else if (User.Status == UserStatus.DataPending)
{
<UserDataSetView></UserDataSetView>
}
else
{
@Body
}
}
} }
else else
{ {
if (uri.LocalPath == "/login") if (User.Status == UserStatus.Banned)
{ {
<Login></Login> <BannedAlert></BannedAlert>
} }
else if (uri.LocalPath == "/register") else if (User.Status == UserStatus.Disabled)
{ {
<Register></Register> <DisabledAlert></DisabledAlert>
} }
else if (uri.LocalPath == "/passwordreset") else if (User.Status == UserStatus.PasswordPending)
{ {
<PasswordReset></PasswordReset> <PasswordChangeView></PasswordChangeView>
}
else if (User.Status == UserStatus.DataPending)
{
<UserDataSetView></UserDataSetView>
}
else
{
@Body
} }
} }
</SoftErrorBoundary> }
</PageErrorBoundary> else
{
if (uri.LocalPath == "/login")
{
<Login></Login>
}
else if (uri.LocalPath == "/register")
{
<Register></Register>
}
else if (uri.LocalPath == "/passwordreset")
{
<PasswordReset></PasswordReset>
}
}
</SoftErrorBoundary>
</div> </div>
</div> </div>
</div> </div>
@@ -161,8 +159,8 @@
await JsRuntime.InvokeVoidAsync("document.body.removeAttribute", "data-kt-app-page-loading"); await JsRuntime.InvokeVoidAsync("document.body.removeAttribute", "data-kt-app-page-loading");
await JsRuntime.InvokeVoidAsync("KTMenu.createInstances"); await JsRuntime.InvokeVoidAsync("KTMenu.createInstances");
await JsRuntime.InvokeVoidAsync("KTDrawer.createInstances"); await JsRuntime.InvokeVoidAsync("KTDrawer.createInstances");
//await JsRuntime.InvokeVoidAsync("createSnow"); //await JsRuntime.InvokeVoidAsync("createSnow");
await SessionService.Register(); await SessionService.Register();

View File

@@ -209,7 +209,9 @@
disk, disk,
User, User,
Model.Image, Model.Image,
DeployNode DeployNode,
null,
Model.Image.Allocations
); );
NavigationManager.NavigateTo($"/server/{server.Uuid}"); NavigationManager.NavigateTo($"/server/{server.Uuid}");

View File

@@ -1,39 +1,12 @@
@page "/test" @page "/test"
@using Moonlight.App.Repositories
@using Moonlight.App.Database.Entities
@using Moonlight.App.Models.Forms
@inject UserRepository UserRepository
<LazyLoader Load="Load"> <LazyLoader Load="Load">
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
<div class="mb-3">
<SmartDropdown
Items="Users"
@bind-Value="Model.User"
DisplayFunc="@(x => x.Email)"
SearchProp="@(x => x.Email)" />
</div>
<div>
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</SmartForm>
</LazyLoader> </LazyLoader>
@code @code
{ {
private User[] Users;
private TestDataModel Model = new();
private Task Load(LazyLoader arg) private Task Load(LazyLoader arg)
{ {
Users = UserRepository.Get().ToArray(); throw new Exception("Nein");
return Task.CompletedTask;
}
private Task OnValidSubmit()
{
return Task.CompletedTask;
} }
} }

View File

@@ -540,3 +540,13 @@ The Email field is required.;The Email field is required.
The Password field is required.;The Password field is required. The Password field is required.;The Password field is required.
The ConfirmPassword field is required.;The ConfirmPassword field is required. The ConfirmPassword field is required.;The ConfirmPassword field is required.
Passwords need to match;Passwords need to match Passwords need to match;Passwords need to match
Cleanup exception;Cleanup exception
No shared domain found;No shared domain found
Searching for deploy plesk server;Searching for deploy plesk server
No plesk server found;No plesk server found
No plesk server found to deploy to;No plesk server found to deploy to
No node found to deploy to;No node found to deploy to
Website details;Website details
Configure your website;Configure your website
The name cannot be longer that 32 characters;The name cannot be longer that 32 characters
The name should only consist of lower case characters;The name should only consist of lower case characters

View File

@@ -83,3 +83,4 @@ Welcome to the support chat. Ask your question here and we will help you;Welcome
less than a minute ago;less than a minute ago less than a minute ago;less than a minute ago
The support team has been notified. Please be patient;The support team has been notified. Please be patient The support team has been notified. Please be patient;The support team has been notified. Please be patient
is typing;is typing is typing;is typing
Proccessing;Proccessing