Refactored css classes to match flyonui. Switched to postgres arrays for permissions. Migrated file manager. Adjusted everything to work with the latest mooncore version

This commit is contained in:
2025-07-12 23:53:43 +02:00
parent eaece9e334
commit d88376f2fb
72 changed files with 2870 additions and 2227 deletions

View File

@@ -45,7 +45,7 @@ public class ApiKeysController : Controller
.Select(x => new ApiKeyResponse()
{
Id = x.Id,
PermissionsJson = x.PermissionsJson,
Permissions = x.Permissions,
Description = x.Description,
ExpiresAt = x.ExpiresAt
})
@@ -75,7 +75,7 @@ public class ApiKeysController : Controller
return new ApiKeyResponse()
{
Id = apiKey.Id,
PermissionsJson = apiKey.PermissionsJson,
Permissions = apiKey.Permissions,
Description = apiKey.Description,
ExpiresAt = apiKey.ExpiresAt
};
@@ -88,7 +88,7 @@ public class ApiKeysController : Controller
var apiKey = new ApiKey()
{
Description = request.Description,
PermissionsJson = request.PermissionsJson,
Permissions = request.Permissions,
ExpiresAt = request.ExpiresAt
};
@@ -97,7 +97,7 @@ public class ApiKeysController : Controller
var response = new CreateApiKeyResponse
{
Id = finalApiKey.Id,
PermissionsJson = finalApiKey.PermissionsJson,
Permissions = finalApiKey.Permissions,
Description = finalApiKey.Description,
ExpiresAt = finalApiKey.ExpiresAt,
Secret = ApiKeyService.GenerateJwt(finalApiKey)
@@ -125,7 +125,7 @@ public class ApiKeysController : Controller
{
Id = apiKey.Id,
Description = apiKey.Description,
PermissionsJson = apiKey.PermissionsJson,
Permissions = apiKey.Permissions,
ExpiresAt = apiKey.ExpiresAt
};
}

View File

@@ -17,8 +17,40 @@ namespace Moonlight.ApiServer.Http.Controllers.Admin.Sys;
public class FilesController : Controller
{
private readonly string BaseDirectory = "storage";
private readonly long ChunkSize = ByteConverter.FromMegaBytes(20).Bytes;
private readonly long MaxChunkSize = ByteConverter.FromMegaBytes(20).Bytes;
[HttpPost("touch")]
public async Task CreateFile([FromQuery] string path)
{
var safePath = SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath);
if (System.IO.File.Exists(physicalPath))
throw new HttpApiException("A file already exists at that path", 400);
if (Directory.Exists(path))
throw new HttpApiException("A folder already exists at that path", 400);
await using var fs = System.IO.File.Create(physicalPath);
fs.Close();
}
[HttpPost("mkdir")]
public Task CreateFolder([FromQuery] string path)
{
var safePath = SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath);
if (Directory.Exists(path))
throw new HttpApiException("A folder already exists at that path", 400);
if (System.IO.File.Exists(physicalPath))
throw new HttpApiException("A file already exists at that path", 400);
Directory.CreateDirectory(physicalPath);
return Task.CompletedTask;
}
[HttpGet("list")]
public Task<FileSystemEntryResponse[]> List([FromQuery] string path)
{
@@ -38,7 +70,7 @@ public class FilesController : Controller
Name = fi.Name,
Size = fi.Length,
CreatedAt = fi.CreationTimeUtc,
IsFile = true,
IsFolder = false,
UpdatedAt = fi.LastWriteTimeUtc
});
}
@@ -55,7 +87,7 @@ public class FilesController : Controller
Size = 0,
CreatedAt = di.CreationTimeUtc,
UpdatedAt = di.LastWriteTimeUtc,
IsFile = false
IsFolder = true
});
}
@@ -65,23 +97,23 @@ public class FilesController : Controller
}
[HttpPost("upload")]
public async Task Upload([FromQuery] string path, [FromQuery] long totalSize, [FromQuery] int chunkId)
public async Task Upload([FromQuery] string path, [FromQuery] long chunkSize, [FromQuery] long totalSize, [FromQuery] int chunkId)
{
if (Request.Form.Files.Count != 1)
throw new HttpApiException("You need to provide exactly one file", 400);
var file = Request.Form.Files[0];
if (file.Length > ChunkSize)
if (file.Length > chunkSize)
throw new HttpApiException("The provided data exceeds the chunk size limit", 400);
var chunks = totalSize / ChunkSize;
chunks += totalSize % ChunkSize > 0 ? 1 : 0;
var chunks = totalSize / chunkSize;
chunks += totalSize % chunkSize > 0 ? 1 : 0;
if (chunkId > chunks)
throw new HttpApiException("Invalid chunk id: Out of bounds", 400);
var positionToSkipTo = ChunkSize * chunkId;
var positionToSkipTo = chunkSize * chunkId;
var safePath = SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath);
@@ -156,16 +188,6 @@ public class FilesController : Controller
return Task.CompletedTask;
}
[HttpPost("mkdir")]
public Task CreateDirectory([FromQuery] string path)
{
var safePath = SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath);
Directory.CreateDirectory(physicalPath);
return Task.CompletedTask;
}
[HttpGet("download")]
public async Task Download([FromQuery] string path)
{
@@ -431,5 +453,23 @@ public class FilesController : Controller
#endregion
private string SanitizePath(string path)
=> path.Replace("..", "");
{
if (string.IsNullOrWhiteSpace(path))
return string.Empty;
// Normalize separators
path = path.Replace('\\', '/');
// Remove ".." and "."
var parts = path.Split('/', StringSplitOptions.RemoveEmptyEntries)
.Where(part => part != ".." && part != ".");
var sanitized = string.Join("/", parts);
// Ensure it does not start with a slash
if (sanitized.StartsWith('/'))
sanitized = sanitized.TrimStart('/');
return sanitized;
}
}

View File

@@ -1,7 +1,5 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MoonCore.Attributes;
using Moonlight.ApiServer.Interfaces;
using Moonlight.ApiServer.Services;
using Moonlight.Shared.Http.Responses.Admin.Sys;
@@ -12,13 +10,10 @@ namespace Moonlight.ApiServer.Http.Controllers.Admin.Sys;
public class SystemController : Controller
{
private readonly ApplicationService ApplicationService;
private readonly IEnumerable<IDiagnoseProvider> DiagnoseProviders;
public SystemController(ApplicationService applicationService, IEnumerable<IDiagnoseProvider> diagnoseProviders)
public SystemController(ApplicationService applicationService)
{
ApplicationService = applicationService;
DiagnoseProviders = diagnoseProviders;
}
[HttpGet]

View File

@@ -45,7 +45,7 @@ public class UsersController : Controller
Id = x.Id,
Email = x.Email,
Username = x.Username,
PermissionsJson = x.PermissionsJson
Permissions = x.Permissions
})
.ToArray();
@@ -75,7 +75,7 @@ public class UsersController : Controller
Id = user.Id,
Email = user.Email,
Username = user.Username,
PermissionsJson = user.PermissionsJson
Permissions = user.Permissions
};
}
@@ -101,7 +101,7 @@ public class UsersController : Controller
Email = request.Email,
Username = request.Username,
Password = hashedPassword,
PermissionsJson = request.PermissionsJson
Permissions = request.Permissions
};
var finalUser = await UserRepository.Add(user);
@@ -111,7 +111,7 @@ public class UsersController : Controller
Id = finalUser.Id,
Email = finalUser.Email,
Username = finalUser.Username,
PermissionsJson = finalUser.PermissionsJson
Permissions = finalUser.Permissions
};
}
@@ -144,9 +144,9 @@ public class UsersController : Controller
user.TokenValidTimestamp = DateTime.UtcNow; // Log out user after password change
}
if (user.PermissionsJson != request.PermissionsJson)
if (request.Permissions.Any(x => !user.Permissions.Contains(x)))
{
user.PermissionsJson = request.PermissionsJson;
user.Permissions = request.Permissions;
user.TokenValidTimestamp = DateTime.UtcNow; // Log out user after permission change
}
@@ -160,7 +160,7 @@ public class UsersController : Controller
Id = user.Id,
Email = user.Email,
Username = user.Username,
PermissionsJson = user.PermissionsJson
Permissions = user.Permissions
};
}