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

@@ -8,12 +8,9 @@ public class ApiKey
public string Description { get; set; }
[Column(TypeName="jsonb")]
public string PermissionsJson { get; set; } = "[]";
public string[] Permissions { get; set; } = [];
[Column(TypeName = "timestamp with time zone")]
public DateTime ExpiresAt { get; set; }
public DateTimeOffset ExpiresAt { get; set; }
[Column(TypeName = "timestamp with time zone")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}

View File

@@ -9,10 +9,6 @@ public class User
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
[Column(TypeName="timestamp with time zone")]
public DateTime TokenValidTimestamp { get; set; } = DateTime.MinValue;
[Column(TypeName="jsonb")]
public string PermissionsJson { get; set; } = "[]";
public DateTimeOffset TokenValidTimestamp { get; set; } = DateTimeOffset.MinValue;
public string[] Permissions { get; set; } = [];
}

View File

@@ -0,0 +1,393 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.ApiServer.Database;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Moonlight.ApiServer.Database.Migrations
{
[DbContext(typeof(CoreDataContext))]
[Migration("20250712202608_SwitchedToPgArraysForPermissions")]
partial class SwitchedToPgArraysForPermissions
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireCounter", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime?>("ExpireAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<long>("Value")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("ExpireAt");
b.HasIndex("Key", "Value");
b.ToTable("HangfireCounter");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireHash", b =>
{
b.Property<string>("Key")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Field")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime?>("ExpireAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("Key", "Field");
b.HasIndex("ExpireAt");
b.ToTable("HangfireHash");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("ExpireAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("InvocationData")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("StateId")
.HasColumnType("bigint");
b.Property<string>("StateName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("ExpireAt");
b.HasIndex("StateId");
b.HasIndex("StateName");
b.ToTable("HangfireJob");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b =>
{
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("JobId", "Name");
b.ToTable("HangfireJobParameter");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireList", b =>
{
b.Property<string>("Key")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<int>("Position")
.HasColumnType("integer");
b.Property<DateTime?>("ExpireAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("Key", "Position");
b.HasIndex("ExpireAt");
b.ToTable("HangfireList");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireLock", b =>
{
b.Property<string>("Id")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("AcquiredAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("HangfireLock");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime?>("FetchedAt")
.IsConcurrencyToken()
.HasColumnType("timestamp with time zone");
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<string>("Queue")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("JobId");
b.HasIndex("Queue", "FetchedAt");
b.ToTable("HangfireQueuedJob");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireServer", b =>
{
b.Property<string>("Id")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("Heartbeat")
.HasColumnType("timestamp with time zone");
b.Property<string>("Queues")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("StartedAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("WorkerCount")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Heartbeat");
b.ToTable("HangfireServer");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireSet", b =>
{
b.Property<string>("Key")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Value")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime?>("ExpireAt")
.HasColumnType("timestamp with time zone");
b.Property<double>("Score")
.HasColumnType("double precision");
b.HasKey("Key", "Value");
b.HasIndex("ExpireAt");
b.HasIndex("Key", "Score");
b.ToTable("HangfireSet");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("text");
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Reason")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("JobId");
b.ToTable("HangfireState");
});
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.PrimitiveCollection<string[]>("Permissions")
.IsRequired()
.HasColumnType("text[]");
b.HasKey("Id");
b.ToTable("Core_ApiKeys", (string)null);
});
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.PrimitiveCollection<string[]>("Permissions")
.IsRequired()
.HasColumnType("text[]");
b.Property<DateTimeOffset>("TokenValidTimestamp")
.HasColumnType("timestamp with time zone");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Core_Users", (string)null);
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
{
b.HasOne("Hangfire.EntityFrameworkCore.HangfireState", "State")
.WithMany()
.HasForeignKey("StateId");
b.Navigation("State");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b =>
{
b.HasOne("Hangfire.EntityFrameworkCore.HangfireJob", "Job")
.WithMany("Parameters")
.HasForeignKey("JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Job");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b =>
{
b.HasOne("Hangfire.EntityFrameworkCore.HangfireJob", "Job")
.WithMany("QueuedJobs")
.HasForeignKey("JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Job");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b =>
{
b.HasOne("Hangfire.EntityFrameworkCore.HangfireJob", "Job")
.WithMany("States")
.HasForeignKey("JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Job");
});
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
{
b.Navigation("Parameters");
b.Navigation("QueuedJobs");
b.Navigation("States");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,62 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.ApiServer.Database.Migrations
{
/// <inheritdoc />
public partial class SwitchedToPgArraysForPermissions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PermissionsJson",
table: "Core_Users");
migrationBuilder.DropColumn(
name: "PermissionsJson",
table: "Core_ApiKeys");
migrationBuilder.AddColumn<string[]>(
name: "Permissions",
table: "Core_Users",
type: "text[]",
nullable: false,
defaultValue: new string[0]);
migrationBuilder.AddColumn<string[]>(
name: "Permissions",
table: "Core_ApiKeys",
type: "text[]",
nullable: false,
defaultValue: new string[0]);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Permissions",
table: "Core_Users");
migrationBuilder.DropColumn(
name: "Permissions",
table: "Core_ApiKeys");
migrationBuilder.AddColumn<string>(
name: "PermissionsJson",
table: "Core_Users",
type: "jsonb",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "PermissionsJson",
table: "Core_ApiKeys",
type: "jsonb",
nullable: false,
defaultValue: "");
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Moonlight.ApiServer.Database.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("ProductVersion", "9.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@@ -283,19 +283,19 @@ namespace Moonlight.ApiServer.Database.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("ExpiresAt")
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("PermissionsJson")
b.PrimitiveCollection<string[]>("Permissions")
.IsRequired()
.HasColumnType("jsonb");
.HasColumnType("text[]");
b.HasKey("Id");
@@ -318,11 +318,11 @@ namespace Moonlight.ApiServer.Database.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<string>("PermissionsJson")
b.PrimitiveCollection<string[]>("Permissions")
.IsRequired()
.HasColumnType("jsonb");
.HasColumnType("text[]");
b.Property<DateTime>("TokenValidTimestamp")
b.Property<DateTimeOffset>("TokenValidTimestamp")
.HasColumnType("timestamp with time zone");
b.Property<string>("Username")

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
};
}

View File

@@ -73,9 +73,6 @@ public class AuthController : Controller
if (user == null)
throw new HttpApiException("Unable to load user data", 500);
//
var permissions = JsonSerializer.Deserialize<string[]>(user.PermissionsJson) ?? [];
// Generate token
var securityTokenDescriptor = new SecurityTokenDescriptor()
{
@@ -90,7 +87,7 @@ public class AuthController : Controller
},
{
"permissions",
string.Join(";", permissions)
string.Join(";", user.Permissions)
}
},
SigningCredentials = new SigningCredentials(
@@ -122,13 +119,11 @@ public class AuthController : Controller
var userId = int.Parse(userIdClaim.Value);
var user = await UserRepository.Get().FirstAsync(x => x.Id == userId);
var permissions = JsonSerializer.Deserialize<string[]>(user.PermissionsJson) ?? [];
return new()
{
Email = user.Email,
Username = user.Username,
Permissions = string.Join(";", permissions)
Permissions = user.Permissions
};
}
}

View File

@@ -1,6 +1,6 @@
@using Moonlight.Shared.Misc
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="bg-background text-base-content font-inter">
<head>
<meta charset="utf-8" />
@@ -18,15 +18,15 @@
<link rel="apple-touch-icon" sizes="192x192" href="/img/icon-192.png" />
</head>
<body class="bg-gray-950 text-white font-inter h-full">
<body>
<div id="app">
<div class="flex h-screen justify-center items-center">
<div class="sm:max-w-lg">
<div id="blazor-loader-label" class="text-center mb-2 text-lg font-semibold"></div>
<div class="flex flex-col gap-1">
<div class="progress min-w-sm md:min-w-md" role="progressbar">
<div id="blazor-loader-progress" class="progress-bar"></div>
<div class="progress h-3 min-w-sm md:min-w-md" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div id="blazor-loader-progress" class="progress-bar progress-primary"></div>
</div>
</div>
</div>

View File

@@ -291,7 +291,7 @@ public partial class OAuth2Controller : Controller
var userCount = await UserRepository.Get().CountAsync();
if (userCount == 0)
user.PermissionsJson = "[\"*\"]";
user.Permissions = ["*"];
}

View File

@@ -89,7 +89,7 @@ public class CoreStartup : IPluginStartup
{
Scripts =
[
"/_content/Moonlight.Client/js/moonlight.js", "/_content/Moonlight.Client/js/moonCore.js",
"/_content/Moonlight.Client/js/moonlight.js", "/_content/MoonCore.Blazor.FlyonUi/moonCore.js",
"/_content/Moonlight.Client/ace/ace.js"
],
Styles = ["/css/style.min.css"]

View File

@@ -20,7 +20,7 @@
</ItemGroup>
<PropertyGroup>
<PackageId>Moonlight.ApiServer</PackageId>
<Version>2.1.1</Version>
<Version>2.1.2</Version>
<Authors>Moonlight Panel</Authors>
<Description>A build of the api server for moonlight development</Description>
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
@@ -34,9 +34,9 @@
<PackageReference Include="Hangfire.EntityFrameworkCore" Version="0.7.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7" />
<PackageReference Include="MoonCore" Version="1.9.1" />
<PackageReference Include="MoonCore" Version="1.9.2" />
<PackageReference Include="MoonCore.Extended" Version="1.3.5" />
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.1" />
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
@@ -58,5 +58,6 @@
<Compile Remove="storage\**\*" />
<Content Remove="storage\**\*" />
<None Remove="storage\**\*" />
<None Remove="Properties\launchSettings.json" />
</ItemGroup>
</Project>

View File

@@ -1,29 +0,0 @@
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5165",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"HTTP_PROXY": "",
"HTTPS_PROXY": ""
},
"hotReloadEnabled": true
},
"WASM Debug": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5165",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"HTTP_PROXY": "",
"HTTPS_PROXY": ""
},
"hotReloadEnabled": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"
}
}
}

View File

@@ -20,13 +20,11 @@ public class ApiKeyService
public string GenerateJwt(ApiKey apiKey)
{
var permissions = JsonSerializer.Deserialize<string[]>(apiKey.PermissionsJson) ?? [];
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var descriptor = new SecurityTokenDescriptor()
{
Expires = apiKey.ExpiresAt,
Expires = apiKey.ExpiresAt.UtcDateTime,
IssuedAt = DateTime.Now,
NotBefore = DateTime.Now.AddMinutes(-1),
Claims = new Dictionary<string, object>()
@@ -37,7 +35,7 @@ public class ApiKeyService
},
{
"permissions",
string.Join(";", permissions)
string.Join(";", apiKey.Permissions)
}
},
SigningCredentials = new SigningCredentials(