Restructure solution to modules structure #22
@@ -12,13 +12,13 @@
|
||||
<IncludeAssets>runtime; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2" />
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2" />
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2"/>
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Moonlight.Api\Moonlight.Api.csproj"/>
|
||||
<ProjectReference Include="..\Moonlight.Frontend.Host\Moonlight.Frontend.Host.csproj" />
|
||||
<ProjectReference Include="..\Moonlight.Frontend.Host\Moonlight.Frontend.Host.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.3" PrivateAssets="all"/>
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2" />
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2" />
|
||||
<PackageReference Include="SimplePlugin" Version="1.0.2"/>
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Moonlight.Frontend\Moonlight.Frontend.csproj" />
|
||||
<ProjectReference Include="..\..\Moonlight.Frontend\Moonlight.Frontend.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Frontend.props"/>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function extractTailwindClasses(opts = {}) {
|
||||
},
|
||||
OnceExit() {
|
||||
const classArray = Array.from(classSet).sort();
|
||||
fs.mkdirSync('../../../Moonlight.Frontend/Styles', { recursive: true });
|
||||
fs.mkdirSync('../../../Moonlight.Frontend/Styles', {recursive: true});
|
||||
fs.writeFileSync('../../../Moonlight.Frontend/Styles/Moonlight.Frontend.map', classArray.join('\n'));
|
||||
console.log(`Extracted classes ${classArray.length}`);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<html class="dark" lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta charset="utf-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>Moonlight</title>
|
||||
<base href="/" />
|
||||
<link rel="preload" id="webassembly" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback" />
|
||||
<link rel="stylesheet" href="style.min.css" />
|
||||
<base href="/"/>
|
||||
<link id="webassembly" rel="preload"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback" rel="stylesheet"/>
|
||||
<link href="style.min.css" rel="stylesheet"/>
|
||||
<script type="importmap"></script>
|
||||
|
||||
<script>
|
||||
@@ -16,7 +16,7 @@
|
||||
STYLE_TAG_ID: 'theme-variables',
|
||||
configuration: {},
|
||||
|
||||
applyTheme: function(cssContent) {
|
||||
applyTheme: function (cssContent) {
|
||||
// Find or create the style tag
|
||||
let styleTag = document.getElementById(this.STYLE_TAG_ID);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
styleTag.textContent = cssContent;
|
||||
},
|
||||
|
||||
reloadConfiguration: function (){
|
||||
reloadConfiguration: function () {
|
||||
try {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/frontend/config', false);
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
},
|
||||
|
||||
getConfiguration: function (){
|
||||
getConfiguration: function () {
|
||||
return this.configuration;
|
||||
},
|
||||
|
||||
@@ -61,48 +61,48 @@
|
||||
</head>
|
||||
|
||||
<body class="bg-background text-foreground">
|
||||
<div id="app">
|
||||
<div class="h-screen w-full flex items-center justify-center">
|
||||
<div id="app">
|
||||
<div class="h-screen w-full flex items-center justify-center">
|
||||
|
||||
<div class="flex min-w-0 flex-1 flex-col items-center justify-center gap-3 rounded-lg border-dashed p-6 text-center text-balance md:p-12">
|
||||
<div class="flex max-w-sm flex-col items-center gap-2 text-center">
|
||||
<div class="flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0 bg-muted text-foreground size-10 rounded-lg [&_svg:not([class*='size-'])]:size-6">
|
||||
<div class="flex min-w-0 flex-1 flex-col items-center justify-center gap-3 rounded-lg border-dashed p-6 text-center text-balance md:p-12">
|
||||
<div class="flex max-w-sm flex-col items-center gap-2 text-center">
|
||||
<div class="flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0 bg-muted text-foreground size-10 rounded-lg [&_svg:not([class*='size-'])]:size-6">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="lucide lucide-zap-icon lucide-zap size-6">
|
||||
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-lg font-medium tracking-tight">
|
||||
Loading application
|
||||
</div>
|
||||
<div class="flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance">
|
||||
|
||||
<div class="bg-primary/20 w-full relative h-2 overflow-hidden rounded-full">
|
||||
<div class="bg-primary h-full w-[var(--blazor-load-percentage,0)] flex-1 transition-all">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<svg class="lucide lucide-zap-icon lucide-zap size-6" fill="none" height="24" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>
|
||||
</svg>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-lg font-medium tracking-tight">
|
||||
Loading application
|
||||
</div>
|
||||
<div class="flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance">
|
||||
|
||||
<div class="bg-primary/20 w-full relative h-2 overflow-hidden rounded-full">
|
||||
<div class="bg-primary h-full w-[var(--blazor-load-percentage,0)] flex-1 transition-all">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="." class="reload">Reload</a>
|
||||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/_content/ShadcnBlazor/interop.js" defer></script>
|
||||
<script src="/_content/ShadcnBlazor.Extras/interop.js" defer></script>
|
||||
<script src="/_content/ShadcnBlazor.Extras/codemirror-bundle.js" defer></script>
|
||||
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a class="reload" href=".">Reload</a>
|
||||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
|
||||
<script defer src="/_content/ShadcnBlazor/interop.js"></script>
|
||||
<script defer src="/_content/ShadcnBlazor.Extras/interop.js"></script>
|
||||
<script defer src="/_content/ShadcnBlazor.Extras/codemirror-bundle.js"></script>
|
||||
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Admin.Sys.Settings;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests.Seup;
|
||||
using Moonlight.Shared.Admin.Setup;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Setup;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/setup")]
|
||||
public class SetupController : Controller
|
||||
{
|
||||
private const string StateSettingsKey = "Moonlight.Api.Setup.State";
|
||||
private readonly DatabaseRepository<Role> RolesRepository;
|
||||
private readonly SettingsService SettingsService;
|
||||
private readonly DatabaseRepository<User> UsersRepository;
|
||||
private readonly DatabaseRepository<Role> RolesRepository;
|
||||
|
||||
private const string StateSettingsKey = "Moonlight.Api.Setup.State";
|
||||
|
||||
public SetupController(
|
||||
SettingsService settingsService,
|
||||
@@ -51,12 +50,12 @@ public class SetupController : Controller
|
||||
.FirstOrDefaultAsync(x => x.Name == "Administrators");
|
||||
|
||||
if (adminRole == null)
|
||||
{
|
||||
adminRole = await RolesRepository.AddAsync(new Role()
|
||||
adminRole = await RolesRepository.AddAsync(new Role
|
||||
{
|
||||
Name = "Administrators",
|
||||
Description = "Automatically generated group for full administrator permissions",
|
||||
Permissions = [
|
||||
Permissions =
|
||||
[
|
||||
Permissions.ApiKeys.View,
|
||||
Permissions.ApiKeys.Create,
|
||||
Permissions.ApiKeys.Edit,
|
||||
@@ -82,10 +81,9 @@ public class SetupController : Controller
|
||||
Permissions.System.Info,
|
||||
Permissions.System.Diagnose,
|
||||
Permissions.System.Versions,
|
||||
Permissions.System.Instance,
|
||||
Permissions.System.Instance
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var user = await UsersRepository
|
||||
@@ -94,12 +92,13 @@ public class SetupController : Controller
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
await UsersRepository.AddAsync(new User()
|
||||
await UsersRepository.AddAsync(new User
|
||||
{
|
||||
Email = dto.AdminEmail,
|
||||
Username = dto.AdminUsername,
|
||||
RoleMemberships = [
|
||||
new RoleMember()
|
||||
RoleMemberships =
|
||||
[
|
||||
new RoleMember
|
||||
{
|
||||
Role = adminRole,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
@@ -112,7 +111,7 @@ public class SetupController : Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
user.RoleMemberships.Add(new RoleMember()
|
||||
user.RoleMemberships.Add(new RoleMember
|
||||
{
|
||||
Role = adminRole,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
@@ -2,25 +2,22 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Implementations.ApiKeyScheme;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Admin.Sys.ApiKeys.Scheme;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests;
|
||||
using Moonlight.Shared.Http.Requests.Admin.ApiKeys;
|
||||
using Moonlight.Shared.Http.Responses;
|
||||
using Moonlight.Shared.Http.Responses.Admin.ApiKeys;
|
||||
using Moonlight.Shared.Admin.Sys.ApiKeys;
|
||||
using Moonlight.Shared.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Sys.ApiKeys;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/admin/apiKeys")]
|
||||
public class ApiKeyController : Controller
|
||||
{
|
||||
private readonly DatabaseRepository<ApiKey> KeyRepository;
|
||||
private readonly HybridCache HybridCache;
|
||||
private readonly DatabaseRepository<ApiKey> KeyRepository;
|
||||
|
||||
public ApiKeyController(DatabaseRepository<ApiKey> keyRepository, HybridCache hybridCache)
|
||||
{
|
||||
@@ -48,9 +45,7 @@ public class ApiKeyController : Controller
|
||||
|
||||
// Filters
|
||||
if (filterOptions != null)
|
||||
{
|
||||
foreach (var filterOption in filterOptions.Filters)
|
||||
{
|
||||
query = filterOption.Key switch
|
||||
{
|
||||
nameof(ApiKey.Name) =>
|
||||
@@ -61,8 +56,6 @@ public class ApiKeyController : Controller
|
||||
|
||||
_ => query
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var data = await query
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Shared.Http.Requests.Admin.ApiKeys;
|
||||
using Moonlight.Shared.Http.Responses.Admin.ApiKeys;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared.Admin.Sys.ApiKeys;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Sys.ApiKeys;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Sys.ApiKeys;
|
||||
|
||||
public class ApiOptions
|
||||
{
|
||||
@@ -5,19 +5,18 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Implementations.ApiKeyScheme;
|
||||
namespace Moonlight.Api.Admin.Sys.ApiKeys.Scheme;
|
||||
|
||||
public class ApiKeySchemeHandler : AuthenticationHandler<ApiKeySchemeOptions>
|
||||
{
|
||||
public const string CacheKeyFormat = $"Moonlight.Api.{nameof(ApiKeySchemeHandler)}.{{0}}";
|
||||
private readonly DatabaseRepository<ApiKey> ApiKeyRepository;
|
||||
private readonly HybridCache HybridCache;
|
||||
|
||||
public const string CacheKeyFormat = $"Moonlight.Api.{nameof(ApiKeySchemeHandler)}.{{0}}";
|
||||
|
||||
public ApiKeySchemeHandler(
|
||||
IOptionsMonitor<ApiKeySchemeOptions> options,
|
||||
ILoggerFactory logger,
|
||||
@@ -50,9 +49,9 @@ public class ApiKeySchemeHandler : AuthenticationHandler<ApiKeySchemeOptions>
|
||||
.Query()
|
||||
.Where(x => x.Key == authHeaderValue)
|
||||
.Select(x => new ApiKeySession(x.Permissions, x.ValidUntil))
|
||||
.FirstOrDefaultAsync(cancellationToken: ct);
|
||||
.FirstOrDefaultAsync(ct);
|
||||
},
|
||||
new HybridCacheEntryOptions()
|
||||
new HybridCacheEntryOptions
|
||||
{
|
||||
LocalCacheExpiration = Options.LookupL1CacheTime,
|
||||
Expiration = Options.LookupL2CacheTime
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Moonlight.Api.Implementations.ApiKeyScheme;
|
||||
namespace Moonlight.Api.Admin.Sys.ApiKeys.Scheme;
|
||||
|
||||
public class ApiKeySchemeOptions : AuthenticationSchemeOptions
|
||||
{
|
||||
@@ -1,24 +1,61 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moonlight.Api.Helpers;
|
||||
using VersionService = Moonlight.Api.Admin.Sys.Versions.VersionService;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Sys;
|
||||
|
||||
public class ApplicationService : IHostedService
|
||||
{
|
||||
private readonly VersionService VersionService;
|
||||
private readonly ILogger<ApplicationService> Logger;
|
||||
private readonly VersionService VersionService;
|
||||
|
||||
public ApplicationService(VersionService versionService, ILogger<ApplicationService> logger)
|
||||
{
|
||||
VersionService = versionService;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public DateTimeOffset StartedAt { get; private set; }
|
||||
public string VersionName { get; private set; } = "N/A";
|
||||
public bool IsUpToDate { get; set; } = true;
|
||||
public string OperatingSystem { get; private set; } = "N/A";
|
||||
|
||||
public ApplicationService(VersionService versionService, ILogger<ApplicationService> logger)
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
VersionService = versionService;
|
||||
Logger = logger;
|
||||
StartedAt = DateTimeOffset.UtcNow;
|
||||
|
||||
OperatingSystem = OsHelper.GetName();
|
||||
|
||||
try
|
||||
{
|
||||
var currentVersion = await VersionService.GetInstanceVersionAsync();
|
||||
var latestVersion = await VersionService.GetLatestVersionAsync();
|
||||
|
||||
VersionName = currentVersion.Identifier;
|
||||
IsUpToDate = latestVersion == null || currentVersion.Identifier == latestVersion.Identifier;
|
||||
|
||||
Logger.LogInformation("Running Moonlight Panel {version} on {operatingSystem}", VersionName,
|
||||
OperatingSystem);
|
||||
|
||||
if (!IsUpToDate)
|
||||
Logger.LogWarning("Your instance is not up-to-date");
|
||||
|
||||
if (currentVersion.IsDevelopment)
|
||||
Logger.LogWarning("Your instance is running a development version");
|
||||
|
||||
if (currentVersion.IsPreRelease)
|
||||
Logger.LogWarning("Your instance is running a pre-release version");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(e, "An unhandled exception occurred while fetching version details");
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<long> GetMemoryUsageAsync()
|
||||
@@ -45,41 +82,8 @@ public class ApplicationService : IHostedService
|
||||
// Calculate CPU usage
|
||||
var cpuUsedMs = (endCpuTime - startCpuTime).TotalMilliseconds;
|
||||
var totalMsPassed = (endTime - startTime).TotalMilliseconds;
|
||||
var cpuUsagePercent = (cpuUsedMs / (Environment.ProcessorCount * totalMsPassed)) * 100;
|
||||
var cpuUsagePercent = cpuUsedMs / (Environment.ProcessorCount * totalMsPassed) * 100;
|
||||
|
||||
return Math.Round(cpuUsagePercent, 2);
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
StartedAt = DateTimeOffset.UtcNow;
|
||||
|
||||
OperatingSystem = OsHelper.GetName();
|
||||
|
||||
try
|
||||
{
|
||||
var currentVersion = await VersionService.GetInstanceVersionAsync();
|
||||
var latestVersion = await VersionService.GetLatestVersionAsync();
|
||||
|
||||
VersionName = currentVersion.Identifier;
|
||||
IsUpToDate = latestVersion == null || currentVersion.Identifier == latestVersion.Identifier;
|
||||
|
||||
Logger.LogInformation("Running Moonlight Panel {version} on {operatingSystem}", VersionName, OperatingSystem);
|
||||
|
||||
if (!IsUpToDate)
|
||||
Logger.LogWarning("Your instance is not up-to-date");
|
||||
|
||||
if (currentVersion.IsDevelopment)
|
||||
Logger.LogWarning("Your instance is running a development version");
|
||||
|
||||
if (currentVersion.IsPreRelease)
|
||||
Logger.LogWarning("Your instance is running a pre-release version");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError(e, "An unhandled exception occurred while fetching version details");
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
@@ -2,14 +2,10 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Configuration;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests.Admin.ContainerHelper;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys.ContainerHelper;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/ch")]
|
||||
@@ -19,7 +15,8 @@ public class ContainerHelperController : Controller
|
||||
private readonly ContainerHelperService ContainerHelperService;
|
||||
private readonly IOptions<ContainerHelperOptions> Options;
|
||||
|
||||
public ContainerHelperController(ContainerHelperService containerHelperService, IOptions<ContainerHelperOptions> options)
|
||||
public ContainerHelperController(ContainerHelperService containerHelperService,
|
||||
IOptions<ContainerHelperOptions> options)
|
||||
{
|
||||
ContainerHelperService = containerHelperService;
|
||||
Options = options;
|
||||
@@ -1,13 +1,13 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Shared.Http.Events;
|
||||
using Moonlight.Shared.Admin.Sys.ContainerHelper;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
[SuppressMessage("Mapper", "RMG012:No members are mapped in an object mapping")]
|
||||
public static partial class ContainerHelperMapper
|
||||
{
|
||||
public static partial RebuildEventDto ToDto(Http.Services.ContainerHelper.Events.RebuildEventDto rebuildEventDto);
|
||||
public static partial RebuildEventDto ToDto(Models.Events.RebuildEventDto rebuildEventDto);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper;
|
||||
|
||||
public class ContainerHelperOptions
|
||||
{
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using Moonlight.Api.Http.Services.ContainerHelper;
|
||||
using Moonlight.Api.Http.Services.ContainerHelper.Requests;
|
||||
using Moonlight.Api.Http.Services.ContainerHelper.Events;
|
||||
using Moonlight.Api.Admin.Sys.ContainerHelper.Models;
|
||||
using Moonlight.Api.Admin.Sys.ContainerHelper.Models.Events;
|
||||
using Moonlight.Api.Admin.Sys.ContainerHelper.Models.Requests;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper;
|
||||
|
||||
public class ContainerHelperService
|
||||
{
|
||||
@@ -53,7 +53,7 @@ public class ContainerHelperService
|
||||
{
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
yield return new RebuildEventDto()
|
||||
yield return new RebuildEventDto
|
||||
{
|
||||
Type = RebuildEventType.Failed,
|
||||
Data = responseText
|
||||
@@ -76,7 +76,8 @@ public class ContainerHelperService
|
||||
continue;
|
||||
|
||||
var data = line.Trim("data: ");
|
||||
var deserializedData = JsonSerializer.Deserialize<RebuildEventDto>(data, SerializationContext.Default.Options);
|
||||
var deserializedData =
|
||||
JsonSerializer.Deserialize<RebuildEventDto>(data, SerializationContext.Default.Options);
|
||||
|
||||
yield return deserializedData;
|
||||
|
||||
@@ -85,7 +86,7 @@ public class ContainerHelperService
|
||||
yield break;
|
||||
} while (true);
|
||||
|
||||
yield return new RebuildEventDto()
|
||||
yield return new RebuildEventDto
|
||||
{
|
||||
Type = RebuildEventType.Succeeded,
|
||||
Data = string.Empty
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper.Models.Events;
|
||||
|
||||
public struct RebuildEventDto
|
||||
{
|
||||
[JsonPropertyName("type")] public RebuildEventType Type { get; set; }
|
||||
|
||||
[JsonPropertyName("data")] public string Data { get; set; }
|
||||
}
|
||||
|
||||
public enum RebuildEventType
|
||||
{
|
||||
Log = 0,
|
||||
Failed = 1,
|
||||
Succeeded = 2,
|
||||
Step = 3
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Http.Services.ContainerHelper;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper.Models;
|
||||
|
||||
public class ProblemDetails
|
||||
{
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper.Models.Requests;
|
||||
|
||||
public record RequestRebuildDto(bool NoBuildCache);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper.Models.Requests;
|
||||
|
||||
public record SetVersionDto(string Version);
|
||||
@@ -1,17 +1,15 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Moonlight.Api.Http.Services.ContainerHelper.Events;
|
||||
using Moonlight.Api.Http.Services.ContainerHelper.Requests;
|
||||
using Moonlight.Api.Admin.Sys.ContainerHelper.Models.Events;
|
||||
using Moonlight.Api.Admin.Sys.ContainerHelper.Models.Requests;
|
||||
|
||||
namespace Moonlight.Api.Http.Services.ContainerHelper;
|
||||
namespace Moonlight.Api.Admin.Sys.ContainerHelper.Models;
|
||||
|
||||
[JsonSerializable(typeof(SetVersionDto))]
|
||||
[JsonSerializable(typeof(ProblemDetails))]
|
||||
[JsonSerializable(typeof(RebuildEventDto))]
|
||||
[JsonSerializable(typeof(RequestRebuildDto))]
|
||||
|
||||
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
|
||||
public partial class SerializationContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys.Diagnose;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Sys.Diagnose;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Policy = Permissions.System.Diagnose)]
|
||||
17
Moonlight.Api/Admin/Sys/Diagnose/DiagnoseResult.cs
Normal file
17
Moonlight.Api/Admin/Sys/Diagnose/DiagnoseResult.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace Moonlight.Api.Admin.Sys.Diagnose;
|
||||
|
||||
public record DiagnoseResult(
|
||||
DiagnoseLevel Level,
|
||||
string Title,
|
||||
string[] Tags,
|
||||
string? Message,
|
||||
string? StackStrace,
|
||||
string? SolutionUrl,
|
||||
string? ReportUrl);
|
||||
|
||||
public enum DiagnoseLevel
|
||||
{
|
||||
Error = 0,
|
||||
Warning = 1,
|
||||
Healthy = 2
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys.Diagnose;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Sys.Diagnose;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
@@ -1,13 +1,12 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moonlight.Api.Interfaces;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Sys.Diagnose;
|
||||
|
||||
public class DiagnoseService
|
||||
{
|
||||
private readonly IEnumerable<IDiagnoseProvider> Providers;
|
||||
private readonly ILogger<DiagnoseService> Logger;
|
||||
private readonly IEnumerable<IDiagnoseProvider> Providers;
|
||||
|
||||
public DiagnoseService(IEnumerable<IDiagnoseProvider> providers, ILogger<DiagnoseService> logger)
|
||||
{
|
||||
@@ -20,7 +19,6 @@ public class DiagnoseService
|
||||
var results = new List<DiagnoseResult>();
|
||||
|
||||
foreach (var provider in Providers)
|
||||
{
|
||||
try
|
||||
{
|
||||
results.AddRange(
|
||||
@@ -31,7 +29,6 @@ public class DiagnoseService
|
||||
{
|
||||
Logger.LogError(e, "An unhandled error occured while processing provider");
|
||||
}
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Moonlight.Api.Helpers;
|
||||
namespace Moonlight.Api.Admin.Sys;
|
||||
|
||||
public class OsHelper
|
||||
{
|
||||
@@ -53,17 +53,12 @@ public class OsHelper
|
||||
string? version = null;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith("NAME="))
|
||||
name = line.Substring(5).Trim('"');
|
||||
else if (line.StartsWith("VERSION_ID="))
|
||||
version = line.Substring(11).Trim('"');
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return string.IsNullOrEmpty(version) ? name : $"{name} {version}";
|
||||
}
|
||||
if (!string.IsNullOrEmpty(name)) return string.IsNullOrEmpty(version) ? name : $"{name} {version}";
|
||||
}
|
||||
|
||||
//If for some weird reason it still uses lsb release
|
||||
@@ -74,17 +69,12 @@ public class OsHelper
|
||||
string? version = null;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith("DISTRIB_ID="))
|
||||
name = line.Substring(11);
|
||||
else if (line.StartsWith("DISTRIB_RELEASE="))
|
||||
version = line.Substring(16);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return string.IsNullOrEmpty(version) ? name : $"{name} {version}";
|
||||
}
|
||||
if (!string.IsNullOrEmpty(name)) return string.IsNullOrEmpty(version) ? name : $"{name} {version}";
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Sys.Settings;
|
||||
|
||||
public class SettingsOptions
|
||||
{
|
||||
@@ -2,25 +2,23 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Configuration;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Sys.Settings;
|
||||
|
||||
public class SettingsService
|
||||
{
|
||||
private readonly DatabaseRepository<SettingsOption> Repository;
|
||||
private readonly IOptions<SettingsOptions> Options;
|
||||
private readonly HybridCache HybridCache;
|
||||
|
||||
private const string CacheKey = "Moonlight.Api.SettingsService.{0}";
|
||||
private readonly HybridCache HybridCache;
|
||||
private readonly IOptions<SettingsOptions> Options;
|
||||
private readonly DatabaseRepository<SettingsOption> Repository;
|
||||
|
||||
public SettingsService(
|
||||
DatabaseRepository<SettingsOption> repository,
|
||||
IOptions<SettingsOptions> options,
|
||||
HybridCache hybridCache
|
||||
)
|
||||
)
|
||||
{
|
||||
Repository = repository;
|
||||
HybridCache = hybridCache;
|
||||
@@ -39,9 +37,9 @@ public class SettingsService
|
||||
.Query()
|
||||
.Where(x => x.Key == key)
|
||||
.Select(o => o.ValueJson)
|
||||
.FirstOrDefaultAsync(cancellationToken: ct);
|
||||
.FirstOrDefaultAsync(ct);
|
||||
},
|
||||
new HybridCacheEntryOptions()
|
||||
new HybridCacheEntryOptions
|
||||
{
|
||||
LocalCacheExpiration = Options.Value.LookupL1CacheTime,
|
||||
Expiration = Options.Value.LookupL2CacheTime
|
||||
@@ -71,7 +69,7 @@ public class SettingsService
|
||||
}
|
||||
else
|
||||
{
|
||||
option = new SettingsOption()
|
||||
option = new SettingsOption
|
||||
{
|
||||
Key = key,
|
||||
ValueJson = json
|
||||
@@ -1,20 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Api.Constants;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Shared.Frontend;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Settings;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Settings;
|
||||
using Moonlight.Shared.Admin.Sys.Settings;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Settings;
|
||||
namespace Moonlight.Api.Admin.Sys.Settings;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Policy = Permissions.System.Settings)]
|
||||
[Route("api/admin/system/settings/whiteLabeling")]
|
||||
public class WhiteLabelingController : Controller
|
||||
{
|
||||
private readonly SettingsService SettingsService;
|
||||
private readonly FrontendService FrontendService;
|
||||
private readonly SettingsService SettingsService;
|
||||
|
||||
public WhiteLabelingController(SettingsService settingsService, FrontendService frontendService)
|
||||
{
|
||||
@@ -1,10 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Sys;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/system")]
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Themes;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Themes;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared.Admin.Sys.Themes;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Sys.Themes;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
@@ -1,6 +1,6 @@
|
||||
using VYaml.Annotations;
|
||||
|
||||
namespace Moonlight.Api.Models;
|
||||
namespace Moonlight.Api.Admin.Sys.Themes;
|
||||
|
||||
[YamlObject]
|
||||
public partial class ThemeTransferModel
|
||||
@@ -1,24 +1,21 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Api.Shared.Frontend;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Themes;
|
||||
using Moonlight.Shared.Http.Responses;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Themes;
|
||||
using Moonlight.Shared.Admin.Sys.Themes;
|
||||
using Moonlight.Shared.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Themes;
|
||||
namespace Moonlight.Api.Admin.Sys.Themes;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/themes")]
|
||||
public class ThemesController : Controller
|
||||
{
|
||||
private readonly DatabaseRepository<Theme> ThemeRepository;
|
||||
private readonly FrontendService FrontendService;
|
||||
private readonly DatabaseRepository<Theme> ThemeRepository;
|
||||
|
||||
public ThemesController(DatabaseRepository<Theme> themeRepository, FrontendService frontendService)
|
||||
{
|
||||
@@ -48,9 +45,7 @@ public class ThemesController : Controller
|
||||
|
||||
// Filters
|
||||
if (filterOptions != null)
|
||||
{
|
||||
foreach (var filterOption in filterOptions.Filters)
|
||||
{
|
||||
query = filterOption.Key switch
|
||||
{
|
||||
nameof(Theme.Name) =>
|
||||
@@ -64,8 +59,6 @@ public class ThemesController : Controller
|
||||
|
||||
_ => query
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var data = await query
|
||||
@@ -1,15 +1,13 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Themes;
|
||||
using Moonlight.Shared.Admin.Sys.Themes;
|
||||
using VYaml.Serialization;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Themes;
|
||||
namespace Moonlight.Api.Admin.Sys.Themes;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/themes")]
|
||||
@@ -33,7 +31,7 @@ public class TransferController : Controller
|
||||
if (theme == null)
|
||||
return Problem("No theme with that id found", statusCode: 404);
|
||||
|
||||
var yml = YamlSerializer.Serialize(new ThemeTransferModel()
|
||||
var yml = YamlSerializer.Serialize(new ThemeTransferModel
|
||||
{
|
||||
Name = theme.Name,
|
||||
Author = theme.Author,
|
||||
@@ -55,7 +53,7 @@ public class TransferController : Controller
|
||||
|
||||
if (existingTheme == null)
|
||||
{
|
||||
var finalTheme = await ThemeRepository.AddAsync(new Theme()
|
||||
var finalTheme = await ThemeRepository.AddAsync(new Theme
|
||||
{
|
||||
Name = themeToImport.Name,
|
||||
Author = themeToImport.Author,
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
public class FrontendOptions
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Models;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
// Notes:
|
||||
// Identifier - This needs to be the branch to clone to build this version if
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys.Versions;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:Source member is not mapped to any target member")]
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
public class VersionOptions
|
||||
{
|
||||
@@ -1,22 +1,16 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Configuration;
|
||||
using Moonlight.Api.Models;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
public partial class VersionService
|
||||
{
|
||||
private readonly IOptions<VersionOptions> Options;
|
||||
private readonly IHttpClientFactory HttpClientFactory;
|
||||
|
||||
private const string VersionPath = "/app/version";
|
||||
private const string GiteaServer = "https://git.battlestati.one";
|
||||
private const string GiteaRepository = "Moonlight-Panel/Moonlight";
|
||||
|
||||
[GeneratedRegex(@"^v(?!1(\.|$))\d+\.[A-Za-z0-9]+(\.[A-Za-z0-9]+)*$")]
|
||||
private static partial Regex RegexFilter();
|
||||
private readonly IHttpClientFactory HttpClientFactory;
|
||||
private readonly IOptions<VersionOptions> Options;
|
||||
|
||||
public VersionService(
|
||||
IOptions<VersionOptions> options,
|
||||
@@ -27,6 +21,9 @@ public partial class VersionService
|
||||
HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"^v(?!1(\.|$))\d+\.[A-Za-z0-9]+(\.[A-Za-z0-9]+)*$")]
|
||||
private static partial Regex RegexFilter();
|
||||
|
||||
public async Task<MoonlightVersion[]> GetVersionsAsync()
|
||||
{
|
||||
if (Options.Value.OfflineMode)
|
||||
@@ -42,7 +39,6 @@ public partial class VersionService
|
||||
var tagsJson = await JsonNode.ParseAsync(tagsJsonStream);
|
||||
|
||||
if (tagsJson != null)
|
||||
{
|
||||
foreach (var node in tagsJson.AsArray())
|
||||
{
|
||||
if (node == null)
|
||||
@@ -51,7 +47,7 @@ public partial class VersionService
|
||||
var name = node["name"]?.GetValue<string>() ?? "N/A";
|
||||
var createdAt = node["createdAt"]?.GetValue<DateTimeOffset>() ?? DateTimeOffset.MinValue;
|
||||
|
||||
if(!RegexFilter().IsMatch(name))
|
||||
if (!RegexFilter().IsMatch(name))
|
||||
continue;
|
||||
|
||||
versions.Add(new MoonlightVersion(
|
||||
@@ -61,7 +57,6 @@ public partial class VersionService
|
||||
createdAt
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Branches
|
||||
const string branchesPath = $"{GiteaServer}/api/v1/repos/{GiteaRepository}/branches";
|
||||
@@ -70,7 +65,6 @@ public partial class VersionService
|
||||
var branchesJson = await JsonNode.ParseAsync(branchesJsonStream);
|
||||
|
||||
if (branchesJson != null)
|
||||
{
|
||||
foreach (var node in branchesJson.AsArray())
|
||||
{
|
||||
if (node == null)
|
||||
@@ -84,7 +78,7 @@ public partial class VersionService
|
||||
|
||||
var createdAt = commit["timestamp"]?.GetValue<DateTimeOffset>() ?? DateTimeOffset.MinValue;
|
||||
|
||||
if(!RegexFilter().IsMatch(name))
|
||||
if (!RegexFilter().IsMatch(name))
|
||||
continue;
|
||||
|
||||
versions.Add(new MoonlightVersion(
|
||||
@@ -94,7 +88,6 @@ public partial class VersionService
|
||||
createdAt
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return versions.ToArray();
|
||||
}
|
||||
@@ -106,7 +99,9 @@ public partial class VersionService
|
||||
string versionIdentifier;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Options.Value.CurrentOverride))
|
||||
{
|
||||
versionIdentifier = Options.Value.CurrentOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(VersionPath))
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Sys.Versions;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Sys.Versions;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/versions")]
|
||||
@@ -38,7 +36,7 @@ public class VersionsController : Controller
|
||||
{
|
||||
var version = await VersionService.GetLatestVersionAsync();
|
||||
|
||||
if(version == null)
|
||||
if (version == null)
|
||||
return Problem("Unable to retrieve latest version", statusCode: 404);
|
||||
|
||||
return VersionMapper.ToDto(version);
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Roles;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared.Admin.Users.Roles;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Users.Roles;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:Source member is not mapped to any target member")]
|
||||
@@ -13,6 +12,7 @@ public static partial class RoleMapper
|
||||
{
|
||||
[MapProperty([nameof(Role.Members), nameof(Role.Members.Count)], nameof(RoleDto.MemberCount))]
|
||||
public static partial RoleDto ToDto(Role role);
|
||||
|
||||
public static partial Role ToEntity(CreateRoleDto request);
|
||||
public static partial void Merge([MappingTarget] Role role, UpdateRoleDto request);
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Admin.Users.Users;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Responses;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Users;
|
||||
using Moonlight.Shared.Admin.Users.Users;
|
||||
using Moonlight.Shared.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Users.Roles;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Policy = Permissions.Roles.Members)]
|
||||
[Route("api/admin/roles/{roleId:int}/members")]
|
||||
public class RoleMembersController : Controller
|
||||
{
|
||||
private readonly DatabaseRepository<User> UsersRepository;
|
||||
private readonly DatabaseRepository<Role> RolesRepository;
|
||||
private readonly DatabaseRepository<RoleMember> RoleMembersRepository;
|
||||
private readonly DatabaseRepository<Role> RolesRepository;
|
||||
private readonly DatabaseRepository<User> UsersRepository;
|
||||
|
||||
public RoleMembersController(
|
||||
DatabaseRepository<User> usersRepository,
|
||||
@@ -53,19 +53,16 @@ public class RoleMembersController : Controller
|
||||
|
||||
// Filtering
|
||||
if (!string.IsNullOrWhiteSpace(searchTerm))
|
||||
{
|
||||
query = query.Where(x =>
|
||||
EF.Functions.ILike(x.Username, $"%{searchTerm}%") ||
|
||||
EF.Functions.ILike(x.Email, $"%{searchTerm}%")
|
||||
);
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var items = query
|
||||
.OrderBy(x => x.Id)
|
||||
.Skip(startIndex)
|
||||
.Take(length)
|
||||
.ProjectToDto()
|
||||
var items = UserMapper.ProjectToDto(query
|
||||
.OrderBy(x => x.Id)
|
||||
.Skip(startIndex)
|
||||
.Take(length))
|
||||
.ToArray();
|
||||
|
||||
var totalCount = await query.CountAsync();
|
||||
@@ -95,19 +92,16 @@ public class RoleMembersController : Controller
|
||||
|
||||
// Filtering
|
||||
if (!string.IsNullOrWhiteSpace(searchTerm))
|
||||
{
|
||||
query = query.Where(x =>
|
||||
EF.Functions.ILike(x.Username, $"%{searchTerm}%") ||
|
||||
EF.Functions.ILike(x.Email, $"%{searchTerm}%")
|
||||
);
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var items = query
|
||||
.OrderBy(x => x.Id)
|
||||
.Skip(startIndex)
|
||||
.Take(length)
|
||||
.ProjectToDto()
|
||||
var items = UserMapper.ProjectToDto(query
|
||||
.OrderBy(x => x.Id)
|
||||
.Skip(startIndex)
|
||||
.Take(length))
|
||||
.ToArray();
|
||||
|
||||
var totalCount = await query.CountAsync();
|
||||
@@ -1,16 +1,13 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Roles;
|
||||
using Moonlight.Shared.Http.Responses;
|
||||
using Moonlight.Shared.Http.Responses.Admin;
|
||||
using Moonlight.Shared.Admin.Users.Roles;
|
||||
using Moonlight.Shared.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin;
|
||||
namespace Moonlight.Api.Admin.Users.Roles;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/roles")]
|
||||
@@ -45,9 +42,7 @@ public class RolesController : Controller
|
||||
|
||||
// Filters
|
||||
if (filterOptions != null)
|
||||
{
|
||||
foreach (var filterOption in filterOptions.Filters)
|
||||
{
|
||||
query = filterOption.Key switch
|
||||
{
|
||||
nameof(Role.Name) =>
|
||||
@@ -55,8 +50,6 @@ public class RolesController : Controller
|
||||
|
||||
_ => query
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var data = await query
|
||||
@@ -3,26 +3,24 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Configuration;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Hooks;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
public class UserAuthService
|
||||
{
|
||||
private readonly DatabaseRepository<User> UserRepository;
|
||||
private readonly ILogger<UserAuthService> Logger;
|
||||
private readonly IOptions<UserOptions> Options;
|
||||
private readonly IEnumerable<IUserAuthHook> Hooks;
|
||||
private readonly HybridCache HybridCache;
|
||||
|
||||
private const string UserIdClaim = "UserId";
|
||||
private const string IssuedAtClaim = "IssuedAt";
|
||||
|
||||
public const string CacheKeyPattern = $"Moonlight.{nameof(UserAuthService)}.{nameof(ValidateAsync)}-{{0}}";
|
||||
private readonly IEnumerable<IUserAuthHook> Hooks;
|
||||
private readonly HybridCache HybridCache;
|
||||
private readonly ILogger<UserAuthService> Logger;
|
||||
private readonly IOptions<UserOptions> Options;
|
||||
private readonly DatabaseRepository<User> UserRepository;
|
||||
|
||||
public UserAuthService(
|
||||
DatabaseRepository<User> userRepository,
|
||||
@@ -60,7 +58,7 @@ public class UserAuthService
|
||||
|
||||
if (user == null) // Sync user if not already existing in the database
|
||||
{
|
||||
user = await UserRepository.AddAsync(new User()
|
||||
user = await UserRepository.AddAsync(new User
|
||||
{
|
||||
Username = username,
|
||||
Email = email,
|
||||
@@ -80,11 +78,9 @@ public class UserAuthService
|
||||
]);
|
||||
|
||||
foreach (var hook in Hooks)
|
||||
{
|
||||
// Run every hook, and if any returns false, we return false as well
|
||||
if (!await hook.SyncAsync(principal, user))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -114,9 +110,9 @@ public class UserAuthService
|
||||
u.InvalidateTimestamp,
|
||||
u.RoleMemberships.SelectMany(x => x.Role.Permissions).ToArray())
|
||||
)
|
||||
.FirstOrDefaultAsync(cancellationToken: ct);
|
||||
.FirstOrDefaultAsync(ct);
|
||||
},
|
||||
new HybridCacheEntryOptions()
|
||||
new HybridCacheEntryOptions
|
||||
{
|
||||
LocalCacheExpiration = Options.Value.ValidationCacheL1Expiry,
|
||||
Expiration = Options.Value.ValidationCacheL2Expiry
|
||||
@@ -146,11 +142,9 @@ public class UserAuthService
|
||||
);
|
||||
|
||||
foreach (var hook in Hooks)
|
||||
{
|
||||
// Run every hook, and if any returns false we return false as well
|
||||
if (!await hook.ValidateAsync(principal, userId))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,21 +1,19 @@
|
||||
using System.Collections.Frozen;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Users;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/users")]
|
||||
[Authorize(Policy = Permissions.Users.Delete)]
|
||||
public class UserDeletionController : Controller
|
||||
{
|
||||
private readonly UserDeletionService UserDeletionService;
|
||||
private readonly DatabaseRepository<User> Repository;
|
||||
private readonly UserDeletionService UserDeletionService;
|
||||
|
||||
public UserDeletionController(UserDeletionService userDeletionService, DatabaseRepository<User> repository)
|
||||
{
|
||||
@@ -36,10 +34,9 @@ public class UserDeletionController : Controller
|
||||
var validationResult = await UserDeletionService.ValidateAsync(id);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
return ValidationProblem(
|
||||
new ValidationProblemDetails(
|
||||
new Dictionary<string, string[]>()
|
||||
new Dictionary<string, string[]>
|
||||
{
|
||||
{
|
||||
string.Empty,
|
||||
@@ -48,7 +45,6 @@ public class UserDeletionController : Controller
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
await UserDeletionService.DeleteAsync(id);
|
||||
return NoContent();
|
||||
@@ -1,22 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
public class UserDeletionService
|
||||
{
|
||||
private readonly DatabaseRepository<User> Repository;
|
||||
private readonly IEnumerable<IUserDeletionHook> Hooks;
|
||||
private readonly HybridCache HybridCache;
|
||||
private readonly DatabaseRepository<User> Repository;
|
||||
|
||||
public UserDeletionService(
|
||||
DatabaseRepository<User> repository,
|
||||
IEnumerable<IUserDeletionHook> hooks,
|
||||
HybridCache hybridCache
|
||||
)
|
||||
)
|
||||
{
|
||||
Repository = repository;
|
||||
Hooks = hooks;
|
||||
@@ -29,7 +29,7 @@ public class UserDeletionService
|
||||
.Query()
|
||||
.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
|
||||
if(user == null)
|
||||
if (user == null)
|
||||
throw new AggregateException($"User with id {userId} not found");
|
||||
|
||||
var errorMessages = new List<string>();
|
||||
@@ -51,7 +51,7 @@ public class UserDeletionService
|
||||
.Query()
|
||||
.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
|
||||
if(user == null)
|
||||
if (user == null)
|
||||
throw new AggregateException($"User with id {userId} not found");
|
||||
|
||||
foreach (var hook in Hooks)
|
||||
@@ -1,12 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Users;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/admin/users/{id:int}/logout")]
|
||||
@@ -1,16 +1,16 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
public class UserLogoutService
|
||||
{
|
||||
private readonly DatabaseRepository<User> Repository;
|
||||
private readonly IEnumerable<IUserLogoutHook> Hooks;
|
||||
private readonly HybridCache HybridCache;
|
||||
private readonly DatabaseRepository<User> Repository;
|
||||
|
||||
public UserLogoutService(
|
||||
DatabaseRepository<User> repository,
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared.Admin.Users.Users;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Users;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Users;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
public class UserOptions
|
||||
{
|
||||
@@ -1,16 +1,13 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
using Moonlight.Shared;
|
||||
using Moonlight.Shared.Http.Requests;
|
||||
using Moonlight.Shared.Http.Requests.Admin.Users;
|
||||
using Moonlight.Shared.Http.Responses;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Users;
|
||||
using Moonlight.Shared.Admin.Users.Users;
|
||||
using Moonlight.Shared.Shared;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers.Admin.Users;
|
||||
namespace Moonlight.Api.Admin.Users.Users;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
@@ -46,21 +43,17 @@ public class UsersController : Controller
|
||||
|
||||
// Filters
|
||||
if (filterOptions != null)
|
||||
{
|
||||
foreach (var filterOption in filterOptions.Filters)
|
||||
{
|
||||
query = filterOption.Key switch
|
||||
{
|
||||
nameof(Database.Entities.User.Email) =>
|
||||
nameof(Infrastructure.Database.Entities.User.Email) =>
|
||||
query.Where(user => EF.Functions.ILike(user.Email, $"%{filterOption.Value}%")),
|
||||
|
||||
nameof(Database.Entities.User.Username) =>
|
||||
nameof(Infrastructure.Database.Entities.User.Username) =>
|
||||
query.Where(user => EF.Functions.ILike(user.Username, $"%{filterOption.Value}%")),
|
||||
|
||||
_ => query
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
var data = await query
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
|
||||
public class Theme
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(30)]
|
||||
public required string Name { get; set; }
|
||||
|
||||
[MaxLength(30)]
|
||||
public required string Version { get; set; }
|
||||
|
||||
[MaxLength(30)]
|
||||
public required string Author { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
[MaxLength(20_000)]
|
||||
public required string CssContent { get; set; }
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Moonlight.Api.Http.Services.ContainerHelper.Events;
|
||||
|
||||
public struct RebuildEventDto
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public RebuildEventType Type { get; set; }
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public string Data { get; set; }
|
||||
}
|
||||
|
||||
public enum RebuildEventType
|
||||
{
|
||||
Log = 0,
|
||||
Failed = 1,
|
||||
Succeeded = 2,
|
||||
Step = 3
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace Moonlight.Api.Http.Services.ContainerHelper.Requests;
|
||||
|
||||
public record RequestRebuildDto(bool NoBuildCache);
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace Moonlight.Api.Http.Services.ContainerHelper.Requests;
|
||||
|
||||
public record SetVersionDto(string Version);
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Infrastructure.Configuration;
|
||||
|
||||
public class CacheOptions
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Infrastructure.Configuration;
|
||||
|
||||
public class OidcOptions
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Infrastructure.Configuration;
|
||||
|
||||
public class RedisOptions
|
||||
{
|
||||
@@ -1,19 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Api.Configuration;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Database;
|
||||
namespace Moonlight.Api.Infrastructure.Database;
|
||||
|
||||
public class DataContext : DbContext
|
||||
{
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<SettingsOption> SettingsOptions { get; set; }
|
||||
public DbSet<Role> Roles { get; set; }
|
||||
public DbSet<RoleMember> RoleMembers { get; set; }
|
||||
public DbSet<ApiKey> ApiKeys { get; set; }
|
||||
public DbSet<Theme> Themes { get; set; }
|
||||
|
||||
private readonly IOptions<DatabaseOptions> Options;
|
||||
|
||||
public DataContext(IOptions<DatabaseOptions> options)
|
||||
@@ -21,6 +13,13 @@ public class DataContext : DbContext
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<SettingsOption> SettingsOptions { get; set; }
|
||||
public DbSet<Role> Roles { get; set; }
|
||||
public DbSet<RoleMember> RoleMembers { get; set; }
|
||||
public DbSet<ApiKey> ApiKeys { get; set; }
|
||||
public DbSet<Theme> Themes { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
if (optionsBuilder.IsConfigured)
|
||||
@@ -31,7 +30,12 @@ public class DataContext : DbContext
|
||||
$"Port={Options.Value.Port};" +
|
||||
$"Username={Options.Value.Username};" +
|
||||
$"Password={Options.Value.Password};" +
|
||||
$"Database={Options.Value.Database}"
|
||||
$"Database={Options.Value.Database}",
|
||||
builder =>
|
||||
{
|
||||
builder.MigrationsAssembly(typeof(DataContext).Assembly);
|
||||
builder.MigrationsHistoryTable("MigrationsHistory", "core");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Configuration;
|
||||
namespace Moonlight.Api.Infrastructure.Database;
|
||||
|
||||
public class DatabaseOptions
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.Api.Database.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
namespace Moonlight.Api.Database;
|
||||
namespace Moonlight.Api.Infrastructure.Database;
|
||||
|
||||
public class DatabaseRepository<T> where T : class
|
||||
{
|
||||
@@ -14,7 +14,10 @@ public class DatabaseRepository<T> where T : class
|
||||
Set = DataContext.Set<T>();
|
||||
}
|
||||
|
||||
public IQueryable<T> Query() => Set;
|
||||
public IQueryable<T> Query()
|
||||
{
|
||||
return Set;
|
||||
}
|
||||
|
||||
public async Task<T> AddAsync(T entity)
|
||||
{
|
||||
@@ -2,9 +2,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moonlight.Api.Database;
|
||||
|
||||
namespace Moonlight.Api.Services;
|
||||
namespace Moonlight.Api.Infrastructure.Database;
|
||||
|
||||
public class DbMigrationService : IHostedLifecycleService
|
||||
{
|
||||
@@ -41,9 +40,28 @@ public class DbMigrationService : IHostedLifecycleService
|
||||
Logger.LogInformation("Migration complete");
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
public Task StartedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
public Task StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StartedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StoppedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StoppingAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.Api.Database.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class ApiKey : IActionTimestamps
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(30)]
|
||||
public required string Name { get; set; }
|
||||
[MaxLength(30)] public required string Name { get; set; }
|
||||
|
||||
[MaxLength(300)]
|
||||
public required string Description { get; set; }
|
||||
[MaxLength(300)] public required string Description { get; set; }
|
||||
|
||||
public string[] Permissions { get; set; } = [];
|
||||
public DateTimeOffset ValidUntil { get; set; }
|
||||
|
||||
[MaxLength(32)]
|
||||
public string Key { get; set; }
|
||||
[MaxLength(32)] public string Key { get; set; }
|
||||
|
||||
// Action timestamps
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
@@ -1,17 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.Api.Database.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class Role : IActionTimestamps
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(30)]
|
||||
public required string Name { get; set; }
|
||||
[MaxLength(30)] public required string Name { get; set; }
|
||||
|
||||
[MaxLength(300)]
|
||||
public required string Description { get; set; }
|
||||
[MaxLength(300)] public required string Description { get; set; }
|
||||
|
||||
public string[] Permissions { get; set; } = [];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Moonlight.Api.Database.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class RoleMember : IActionTimestamps
|
||||
{
|
||||
@@ -1,14 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class SettingsOption
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(256)]
|
||||
public required string Key { get; set; }
|
||||
[MaxLength(256)] public required string Key { get; set; }
|
||||
|
||||
[MaxLength(4096)]
|
||||
[Column(TypeName = "jsonb")]
|
||||
18
Moonlight.Api/Infrastructure/Database/Entities/Theme.cs
Normal file
18
Moonlight.Api/Infrastructure/Database/Entities/Theme.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class Theme
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(30)] public required string Name { get; set; }
|
||||
|
||||
[MaxLength(30)] public required string Version { get; set; }
|
||||
|
||||
[MaxLength(30)] public required string Author { get; set; }
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
[MaxLength(20_000)] public required string CssContent { get; set; }
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Moonlight.Api.Database.Interfaces;
|
||||
using Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
namespace Moonlight.Api.Database.Entities;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
public class User : IActionTimestamps
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
// Base information
|
||||
[MaxLength(50)]
|
||||
public required string Username { get; set; }
|
||||
[MaxLength(50)] public required string Username { get; set; }
|
||||
|
||||
[MaxLength(254)]
|
||||
public required string Email { get; set; }
|
||||
[MaxLength(254)] public required string Email { get; set; }
|
||||
|
||||
// Authentication
|
||||
public DateTimeOffset InvalidateTimestamp { get; set; }
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Moonlight.Api.Database.Interfaces;
|
||||
namespace Moonlight.Api.Infrastructure.Database.Interfaces;
|
||||
|
||||
internal interface IActionTimestamps
|
||||
{
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.Api.Database;
|
||||
using Moonlight.Api.Infrastructure.Database;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Console;
|
||||
|
||||
namespace Moonlight.Api.Helpers;
|
||||
namespace Moonlight.Api.Infrastructure.Helpers;
|
||||
|
||||
public class AppConsoleFormatter : ConsoleFormatter
|
||||
{
|
||||
@@ -58,7 +58,9 @@ public class AppConsoleFormatter : ConsoleFormatter
|
||||
textWriter.WriteLine(logEntry.Exception.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
textWriter.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static (string text, string color) GetLevelInfo(LogLevel logLevel)
|
||||
@@ -1,6 +1,6 @@
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Api.Admin.Sys.Diagnose;
|
||||
|
||||
namespace Moonlight.Api.Interfaces;
|
||||
namespace Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
public interface IDiagnoseProvider
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Security.Claims;
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Interfaces;
|
||||
namespace Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
public interface IUserAuthHook
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using Moonlight.Api.Database.Entities;
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Interfaces;
|
||||
namespace Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
public interface IUserDeletionHook
|
||||
{
|
||||
8
Moonlight.Api/Infrastructure/Hooks/IUserLogoutHook.cs
Normal file
8
Moonlight.Api/Infrastructure/Hooks/IUserLogoutHook.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Moonlight.Api.Infrastructure.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
public interface IUserLogoutHook
|
||||
{
|
||||
public Task ExecuteAsync(User user);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Implementations;
|
||||
namespace Moonlight.Api.Infrastructure.Implementations;
|
||||
|
||||
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
|
||||
{
|
||||
@@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moonlight.Shared;
|
||||
|
||||
namespace Moonlight.Api.Implementations;
|
||||
namespace Moonlight.Api.Infrastructure.Implementations;
|
||||
|
||||
public class PermissionPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
@@ -25,18 +25,22 @@ public class PermissionPolicyProvider : IAuthorizationPolicyProvider
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
|
||||
=> FallbackProvider.GetDefaultPolicyAsync();
|
||||
{
|
||||
return FallbackProvider.GetDefaultPolicyAsync();
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy?> GetFallbackPolicyAsync()
|
||||
=> FallbackProvider.GetFallbackPolicyAsync();
|
||||
{
|
||||
return FallbackProvider.GetFallbackPolicyAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class PermissionRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public string Identifier { get; }
|
||||
|
||||
public PermissionRequirement(string identifier)
|
||||
{
|
||||
Identifier = identifier;
|
||||
}
|
||||
|
||||
public string Identifier { get; }
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using Moonlight.Api.Interfaces;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Api.Admin.Sys;
|
||||
using Moonlight.Api.Admin.Sys.Diagnose;
|
||||
using Moonlight.Api.Infrastructure.Hooks;
|
||||
|
||||
namespace Moonlight.Api.Implementations;
|
||||
namespace Moonlight.Api.Infrastructure.Implementations;
|
||||
|
||||
public sealed class UpdateDiagnoseProvider : IDiagnoseProvider
|
||||
{
|
||||
@@ -1,8 +0,0 @@
|
||||
using Moonlight.Api.Database.Entities;
|
||||
|
||||
namespace Moonlight.Api.Interfaces;
|
||||
|
||||
public interface IUserLogoutHook
|
||||
{
|
||||
public Task ExecuteAsync(User user);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Moonlight.Api.Models;
|
||||
|
||||
public record DiagnoseResult(DiagnoseLevel Level, string Title, string[] Tags, string? Message, string? StackStrace, string? SolutionUrl, string? ReportUrl);
|
||||
|
||||
public enum DiagnoseLevel
|
||||
{
|
||||
Error = 0,
|
||||
Warning = 1,
|
||||
Healthy = 2
|
||||
}
|
||||
@@ -27,12 +27,12 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.3"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.3"/>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="10.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="10.3.0"/>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.3"/>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0"/>
|
||||
<PackageReference Include="Riok.Mapperly" Version="4.3.1"/>
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2" />
|
||||
<PackageReference Include="VYaml" Version="1.2.0" />
|
||||
<PackageReference Include="SimplePlugin.Abstractions" Version="1.0.2"/>
|
||||
<PackageReference Include="VYaml" Version="1.2.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -42,6 +42,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Http\Services\ContainerHelper\Responses\" />
|
||||
<Folder Include="Client\"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using SimplePlugin.Abstractions;
|
||||
|
||||
namespace Moonlight.Api;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Auth;
|
||||
using Moonlight.Shared.Shared.Auth;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers;
|
||||
namespace Moonlight.Api.Shared.Auth;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/auth")]
|
||||
@@ -35,7 +35,7 @@ public class AuthController : Controller
|
||||
if (scheme == null || string.IsNullOrWhiteSpace(scheme.DisplayName))
|
||||
return Problem("Invalid authentication scheme name", statusCode: 400);
|
||||
|
||||
return Challenge(new AuthenticationProperties()
|
||||
return Challenge(new AuthenticationProperties
|
||||
{
|
||||
RedirectUri = "/"
|
||||
}, scheme.Name);
|
||||
@@ -56,7 +56,7 @@ public class AuthController : Controller
|
||||
public Task<ActionResult> LogoutAsync()
|
||||
{
|
||||
return Task.FromResult<ActionResult>(
|
||||
SignOut(new AuthenticationProperties()
|
||||
SignOut(new AuthenticationProperties
|
||||
{
|
||||
RedirectUri = "/"
|
||||
})
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Moonlight.Api.Models;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Frontend;
|
||||
using Moonlight.Shared.Shared.Frontend;
|
||||
using Riok.Mapperly.Abstractions;
|
||||
|
||||
namespace Moonlight.Api.Mappers;
|
||||
namespace Moonlight.Api.Shared.Frontend;
|
||||
|
||||
[Mapper]
|
||||
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
|
||||
@@ -1,3 +1,3 @@
|
||||
namespace Moonlight.Api.Models;
|
||||
namespace Moonlight.Api.Shared.Frontend;
|
||||
|
||||
public record FrontendConfiguration(string Name, string? ThemeCss);
|
||||
@@ -1,9 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.Api.Mappers;
|
||||
using Moonlight.Api.Services;
|
||||
using Moonlight.Shared.Http.Responses.Admin.Frontend;
|
||||
using Moonlight.Shared.Shared.Frontend;
|
||||
|
||||
namespace Moonlight.Api.Http.Controllers;
|
||||
namespace Moonlight.Api.Shared.Frontend;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/frontend")]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user