Switched to database scheme seperation from MoonCores SingleDb. Updated mooncore versions. Updating to correct Async naming

This commit is contained in:
2025-09-21 16:44:01 +00:00
parent 86bec7f2ee
commit 3e87d5c140
93 changed files with 587 additions and 1583 deletions

View File

@@ -10,15 +10,15 @@ await startup.Run(args, pluginLoader.Instances);
var cs = new Startup(); var cs = new Startup();
await cs.Initialize(args, pluginLoader.Instances); await cs.InitializeAsync(args, pluginLoader.Instances);
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
await cs.AddMoonlight(builder); await cs.AddMoonlightAsync(builder);
var app = builder.Build(); var app = builder.Build();
await cs.AddMoonlight(app); await cs.AddMoonlightAsync(app);
// Handle setup of wasm app hosting in the runtime // Handle setup of wasm app hosting in the runtime
// so the Moonlight.ApiServer doesn't need the wasm package // so the Moonlight.ApiServer doesn't need the wasm package

View File

@@ -62,7 +62,7 @@ public record AppConfiguration
public record FilesData public record FilesData
{ {
[YamlMember(Description = "The maximum file size limit a combine operation is allowed to process")] [YamlMember(Description = "The maximum file size limit a combine operation is allowed to process")]
public long CombineLimit { get; set; } = ByteConverter.FromGigaBytes(5).MegaBytes; public double CombineLimit { get; set; } = ByteConverter.FromGigaBytes(5).MegaBytes;
} }
public record FrontendData public record FrontendData

View File

@@ -1,15 +1,14 @@
using Hangfire.EntityFrameworkCore; using Hangfire.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using MoonCore.Extended.SingleDb;
using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Configuration;
using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Database.Entities;
using Moonlight.ApiServer.Models; using Moonlight.ApiServer.Models;
namespace Moonlight.ApiServer.Database; namespace Moonlight.ApiServer.Database;
public class CoreDataContext : DatabaseContext public class CoreDataContext : DbContext
{ {
public override string Prefix { get; } = "Core"; private readonly AppConfiguration Configuration;
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<ApiKey> ApiKeys { get; set; } public DbSet<ApiKey> ApiKeys { get; set; }
@@ -17,18 +16,32 @@ public class CoreDataContext : DatabaseContext
public CoreDataContext(AppConfiguration configuration) public CoreDataContext(AppConfiguration configuration)
{ {
Options = new() Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
Host = configuration.Database.Host, if(optionsBuilder.IsConfigured)
Port = configuration.Database.Port, return;
Username = configuration.Database.Username,
Password = configuration.Database.Password, var database = Configuration.Database;
Database = configuration.Database.Database
}; var connectionString = $"Host={database.Host};" +
$"Port={database.Port};" +
$"Database={database.Database};" +
$"Username={database.Username};" +
$"Password={database.Password}";
optionsBuilder.UseNpgsql(connectionString, builder =>
{
builder.MigrationsHistoryTable("MigrationsHistory", "core");
});
} }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Model.SetDefaultSchema("core");
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.OnHangfireModelCreating(); modelBuilder.OnHangfireModelCreating();

View File

@@ -1,90 +0,0 @@
// <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("20250226080942_AddedUsersAndApiKey")]
partial class AddedUsersAndApiKey
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<string>("Secret")
.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.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("timestamp with time zone");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Core_Users", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,59 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Moonlight.ApiServer.Database.Migrations
{
/// <inheritdoc />
public partial class AddedUsersAndApiKey : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Core_ApiKeys",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Secret = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
PermissionsJson = table.Column<string>(type: "jsonb", nullable: false),
ExpiresAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Core_ApiKeys", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Core_Users",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Username = table.Column<string>(type: "text", nullable: false),
Email = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
TokenValidTimestamp = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
PermissionsJson = table.Column<string>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Core_Users", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Core_ApiKeys");
migrationBuilder.DropTable(
name: "Core_Users");
}
}
}

View File

@@ -1,89 +0,0 @@
// <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("20250314095412_ModifiedApiKeyEntity")]
partial class ModifiedApiKeyEntity
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
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.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("timestamp with time zone");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Core_Users", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,41 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.ApiServer.Database.Migrations
{
/// <inheritdoc />
public partial class ModifiedApiKeyEntity : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Secret",
table: "Core_ApiKeys");
migrationBuilder.AddColumn<DateTime>(
name: "CreatedAt",
table: "Core_ApiKeys",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CreatedAt",
table: "Core_ApiKeys");
migrationBuilder.AddColumn<string>(
name: "Secret",
table: "Core_ApiKeys",
type: "text",
nullable: false,
defaultValue: "");
}
}
}

View File

@@ -1,393 +0,0 @@
// <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("20250405172522_AddedHangfireTables")]
partial class AddedHangfireTables
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.11")
.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<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
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.Property<string>("PermissionsJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("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

@@ -1,393 +0,0 @@
// <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

@@ -1,62 +0,0 @@
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

@@ -1,41 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Moonlight.ApiServer.Database.Migrations
{
/// <inheritdoc />
public partial class AddedThemes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Core_Themes",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Author = table.Column<string>(type: "text", nullable: false),
Version = table.Column<string>(type: "text", nullable: false),
UpdateUrl = table.Column<string>(type: "text", nullable: true),
DonateUrl = table.Column<string>(type: "text", nullable: true),
Content = table.Column<string>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Core_Themes", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Core_Themes");
}
}
}

View File

@@ -12,15 +12,16 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Moonlight.ApiServer.Database.Migrations namespace Moonlight.ApiServer.Database.Migrations
{ {
[DbContext(typeof(CoreDataContext))] [DbContext(typeof(CoreDataContext))]
[Migration("20250720203346_AddedThemes")] [Migration("20250919201409_RecreatedMigrationsForChangeOfSchema")]
partial class AddedThemes partial class RecreatedMigrationsForChangeOfSchema
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "9.0.7") .HasDefaultSchema("core")
.HasAnnotation("ProductVersion", "9.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63); .HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@@ -50,7 +51,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Key", "Value"); b.HasIndex("Key", "Value");
b.ToTable("HangfireCounter"); b.ToTable("HangfireCounter", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireHash", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireHash", b =>
@@ -73,7 +74,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("ExpireAt"); b.HasIndex("ExpireAt");
b.ToTable("HangfireHash"); b.ToTable("HangfireHash", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
@@ -109,7 +110,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("StateName"); b.HasIndex("StateName");
b.ToTable("HangfireJob"); b.ToTable("HangfireJob", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b =>
@@ -126,7 +127,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("JobId", "Name"); b.HasKey("JobId", "Name");
b.ToTable("HangfireJobParameter"); b.ToTable("HangfireJobParameter", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireList", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireList", b =>
@@ -148,7 +149,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("ExpireAt"); b.HasIndex("ExpireAt");
b.ToTable("HangfireList"); b.ToTable("HangfireList", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireLock", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireLock", b =>
@@ -162,7 +163,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("HangfireLock"); b.ToTable("HangfireLock", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b =>
@@ -191,7 +192,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Queue", "FetchedAt"); b.HasIndex("Queue", "FetchedAt");
b.ToTable("HangfireQueuedJob"); b.ToTable("HangfireQueuedJob", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireServer", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireServer", b =>
@@ -217,7 +218,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Heartbeat"); b.HasIndex("Heartbeat");
b.ToTable("HangfireServer"); b.ToTable("HangfireServer", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireSet", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireSet", b =>
@@ -242,7 +243,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Key", "Score"); b.HasIndex("Key", "Score");
b.ToTable("HangfireSet"); b.ToTable("HangfireSet", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b =>
@@ -275,7 +276,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("JobId"); b.HasIndex("JobId");
b.ToTable("HangfireState"); b.ToTable("HangfireState", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b =>
@@ -302,7 +303,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_ApiKeys", (string)null); b.ToTable("ApiKeys", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.Theme", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.Theme", b =>
@@ -336,7 +337,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_Themes", (string)null); b.ToTable("Themes", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.User", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.User", b =>
@@ -368,7 +369,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_Users", (string)null); b.ToTable("Users", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
@@ -515,11 +516,11 @@ namespace Moonlight.ApiServer.Database.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b1.Property<float>("Depth") b1.Property<int>("Depth")
.HasColumnType("real"); .HasColumnType("integer");
b1.Property<float>("Noise") b1.Property<int>("Noise")
.HasColumnType("real"); .HasColumnType("integer");
b1.Property<float>("RadiusBox") b1.Property<float>("RadiusBox")
.HasColumnType("real"); .HasColumnType("real");
@@ -538,7 +539,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b1.HasKey("ThemeId"); b1.HasKey("ThemeId");
b1.ToTable("Core_Themes"); b1.ToTable("Themes", "core");
b1.ToJson("Content"); b1.ToJson("Content");

View File

@@ -7,13 +7,34 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Moonlight.ApiServer.Database.Migrations namespace Moonlight.ApiServer.Database.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class AddedHangfireTables : Migration public partial class RecreatedMigrationsForChangeOfSchema : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.EnsureSchema(
name: "core");
migrationBuilder.CreateTable(
name: "ApiKeys",
schema: "core",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Description = table.Column<string>(type: "text", nullable: false),
Permissions = table.Column<string[]>(type: "text[]", nullable: false),
ExpiresAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiKeys", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireCounter", name: "HangfireCounter",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<long>(type: "bigint", nullable: false) Id = table.Column<long>(type: "bigint", nullable: false)
@@ -29,6 +50,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireHash", name: "HangfireHash",
schema: "core",
columns: table => new columns: table => new
{ {
Key = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false), Key = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
@@ -43,6 +65,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireList", name: "HangfireList",
schema: "core",
columns: table => new columns: table => new
{ {
Key = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false), Key = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
@@ -57,6 +80,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireLock", name: "HangfireLock",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false), Id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
@@ -69,6 +93,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireServer", name: "HangfireServer",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false), Id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
@@ -84,6 +109,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireSet", name: "HangfireSet",
schema: "core",
columns: table => new columns: table => new
{ {
Key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false), Key = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
@@ -96,8 +122,47 @@ namespace Moonlight.ApiServer.Database.Migrations
table.PrimaryKey("PK_HangfireSet", x => new { x.Key, x.Value }); table.PrimaryKey("PK_HangfireSet", x => new { x.Key, x.Value });
}); });
migrationBuilder.CreateTable(
name: "Themes",
schema: "core",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Author = table.Column<string>(type: "text", nullable: false),
Version = table.Column<string>(type: "text", nullable: false),
UpdateUrl = table.Column<string>(type: "text", nullable: true),
DonateUrl = table.Column<string>(type: "text", nullable: true),
Content = table.Column<string>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Themes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
schema: "core",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Username = table.Column<string>(type: "text", nullable: false),
Email = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
TokenValidTimestamp = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
Permissions = table.Column<string[]>(type: "text[]", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireJob", name: "HangfireJob",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<long>(type: "bigint", nullable: false) Id = table.Column<long>(type: "bigint", nullable: false)
@@ -115,6 +180,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireJobParameter", name: "HangfireJobParameter",
schema: "core",
columns: table => new columns: table => new
{ {
JobId = table.Column<long>(type: "bigint", nullable: false), JobId = table.Column<long>(type: "bigint", nullable: false),
@@ -127,6 +193,7 @@ namespace Moonlight.ApiServer.Database.Migrations
table.ForeignKey( table.ForeignKey(
name: "FK_HangfireJobParameter_HangfireJob_JobId", name: "FK_HangfireJobParameter_HangfireJob_JobId",
column: x => x.JobId, column: x => x.JobId,
principalSchema: "core",
principalTable: "HangfireJob", principalTable: "HangfireJob",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
@@ -134,6 +201,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireQueuedJob", name: "HangfireQueuedJob",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<long>(type: "bigint", nullable: false) Id = table.Column<long>(type: "bigint", nullable: false)
@@ -148,6 +216,7 @@ namespace Moonlight.ApiServer.Database.Migrations
table.ForeignKey( table.ForeignKey(
name: "FK_HangfireQueuedJob_HangfireJob_JobId", name: "FK_HangfireQueuedJob_HangfireJob_JobId",
column: x => x.JobId, column: x => x.JobId,
principalSchema: "core",
principalTable: "HangfireJob", principalTable: "HangfireJob",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
@@ -155,6 +224,7 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "HangfireState", name: "HangfireState",
schema: "core",
columns: table => new columns: table => new
{ {
Id = table.Column<long>(type: "bigint", nullable: false) Id = table.Column<long>(type: "bigint", nullable: false)
@@ -171,6 +241,7 @@ namespace Moonlight.ApiServer.Database.Migrations
table.ForeignKey( table.ForeignKey(
name: "FK_HangfireState_HangfireJob_JobId", name: "FK_HangfireState_HangfireJob_JobId",
column: x => x.JobId, column: x => x.JobId,
principalSchema: "core",
principalTable: "HangfireJob", principalTable: "HangfireJob",
principalColumn: "Id", principalColumn: "Id",
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
@@ -178,73 +249,88 @@ namespace Moonlight.ApiServer.Database.Migrations
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireCounter_ExpireAt", name: "IX_HangfireCounter_ExpireAt",
schema: "core",
table: "HangfireCounter", table: "HangfireCounter",
column: "ExpireAt"); column: "ExpireAt");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireCounter_Key_Value", name: "IX_HangfireCounter_Key_Value",
schema: "core",
table: "HangfireCounter", table: "HangfireCounter",
columns: new[] { "Key", "Value" }); columns: new[] { "Key", "Value" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireHash_ExpireAt", name: "IX_HangfireHash_ExpireAt",
schema: "core",
table: "HangfireHash", table: "HangfireHash",
column: "ExpireAt"); column: "ExpireAt");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireJob_ExpireAt", name: "IX_HangfireJob_ExpireAt",
schema: "core",
table: "HangfireJob", table: "HangfireJob",
column: "ExpireAt"); column: "ExpireAt");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireJob_StateId", name: "IX_HangfireJob_StateId",
schema: "core",
table: "HangfireJob", table: "HangfireJob",
column: "StateId"); column: "StateId");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireJob_StateName", name: "IX_HangfireJob_StateName",
schema: "core",
table: "HangfireJob", table: "HangfireJob",
column: "StateName"); column: "StateName");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireList_ExpireAt", name: "IX_HangfireList_ExpireAt",
schema: "core",
table: "HangfireList", table: "HangfireList",
column: "ExpireAt"); column: "ExpireAt");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireQueuedJob_JobId", name: "IX_HangfireQueuedJob_JobId",
schema: "core",
table: "HangfireQueuedJob", table: "HangfireQueuedJob",
column: "JobId"); column: "JobId");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireQueuedJob_Queue_FetchedAt", name: "IX_HangfireQueuedJob_Queue_FetchedAt",
schema: "core",
table: "HangfireQueuedJob", table: "HangfireQueuedJob",
columns: new[] { "Queue", "FetchedAt" }); columns: new[] { "Queue", "FetchedAt" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireServer_Heartbeat", name: "IX_HangfireServer_Heartbeat",
schema: "core",
table: "HangfireServer", table: "HangfireServer",
column: "Heartbeat"); column: "Heartbeat");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireSet_ExpireAt", name: "IX_HangfireSet_ExpireAt",
schema: "core",
table: "HangfireSet", table: "HangfireSet",
column: "ExpireAt"); column: "ExpireAt");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireSet_Key_Score", name: "IX_HangfireSet_Key_Score",
schema: "core",
table: "HangfireSet", table: "HangfireSet",
columns: new[] { "Key", "Score" }); columns: new[] { "Key", "Score" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_HangfireState_JobId", name: "IX_HangfireState_JobId",
schema: "core",
table: "HangfireState", table: "HangfireState",
column: "JobId"); column: "JobId");
migrationBuilder.AddForeignKey( migrationBuilder.AddForeignKey(
name: "FK_HangfireJob_HangfireState_StateId", name: "FK_HangfireJob_HangfireState_StateId",
schema: "core",
table: "HangfireJob", table: "HangfireJob",
column: "StateId", column: "StateId",
principalSchema: "core",
principalTable: "HangfireState", principalTable: "HangfireState",
principalColumn: "Id"); principalColumn: "Id");
} }
@@ -254,37 +340,60 @@ namespace Moonlight.ApiServer.Database.Migrations
{ {
migrationBuilder.DropForeignKey( migrationBuilder.DropForeignKey(
name: "FK_HangfireJob_HangfireState_StateId", name: "FK_HangfireJob_HangfireState_StateId",
schema: "core",
table: "HangfireJob"); table: "HangfireJob");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireCounter"); name: "ApiKeys",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireHash"); name: "HangfireCounter",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireJobParameter"); name: "HangfireHash",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireList"); name: "HangfireJobParameter",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireLock"); name: "HangfireList",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireQueuedJob"); name: "HangfireLock",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireServer"); name: "HangfireQueuedJob",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireSet"); name: "HangfireServer",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireState"); name: "HangfireSet",
schema: "core");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "HangfireJob"); name: "Themes",
schema: "core");
migrationBuilder.DropTable(
name: "Users",
schema: "core");
migrationBuilder.DropTable(
name: "HangfireState",
schema: "core");
migrationBuilder.DropTable(
name: "HangfireJob",
schema: "core");
} }
} }
} }

View File

@@ -17,7 +17,8 @@ namespace Moonlight.ApiServer.Database.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "9.0.7") .HasDefaultSchema("core")
.HasAnnotation("ProductVersion", "9.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63); .HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@@ -47,7 +48,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Key", "Value"); b.HasIndex("Key", "Value");
b.ToTable("HangfireCounter"); b.ToTable("HangfireCounter", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireHash", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireHash", b =>
@@ -70,7 +71,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("ExpireAt"); b.HasIndex("ExpireAt");
b.ToTable("HangfireHash"); b.ToTable("HangfireHash", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
@@ -106,7 +107,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("StateName"); b.HasIndex("StateName");
b.ToTable("HangfireJob"); b.ToTable("HangfireJob", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJobParameter", b =>
@@ -123,7 +124,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("JobId", "Name"); b.HasKey("JobId", "Name");
b.ToTable("HangfireJobParameter"); b.ToTable("HangfireJobParameter", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireList", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireList", b =>
@@ -145,7 +146,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("ExpireAt"); b.HasIndex("ExpireAt");
b.ToTable("HangfireList"); b.ToTable("HangfireList", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireLock", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireLock", b =>
@@ -159,7 +160,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("HangfireLock"); b.ToTable("HangfireLock", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireQueuedJob", b =>
@@ -188,7 +189,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Queue", "FetchedAt"); b.HasIndex("Queue", "FetchedAt");
b.ToTable("HangfireQueuedJob"); b.ToTable("HangfireQueuedJob", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireServer", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireServer", b =>
@@ -214,7 +215,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Heartbeat"); b.HasIndex("Heartbeat");
b.ToTable("HangfireServer"); b.ToTable("HangfireServer", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireSet", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireSet", b =>
@@ -239,7 +240,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("Key", "Score"); b.HasIndex("Key", "Score");
b.ToTable("HangfireSet"); b.ToTable("HangfireSet", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireState", b =>
@@ -272,7 +273,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasIndex("JobId"); b.HasIndex("JobId");
b.ToTable("HangfireState"); b.ToTable("HangfireState", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.ApiKey", b =>
@@ -299,7 +300,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_ApiKeys", (string)null); b.ToTable("ApiKeys", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.Theme", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.Theme", b =>
@@ -333,7 +334,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_Themes", (string)null); b.ToTable("Themes", "core");
}); });
modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.User", b => modelBuilder.Entity("Moonlight.ApiServer.Database.Entities.User", b =>
@@ -365,7 +366,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Core_Users", (string)null); b.ToTable("Users", "core");
}); });
modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b => modelBuilder.Entity("Hangfire.EntityFrameworkCore.HangfireJob", b =>
@@ -512,11 +513,11 @@ namespace Moonlight.ApiServer.Database.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b1.Property<float>("Depth") b1.Property<int>("Depth")
.HasColumnType("real"); .HasColumnType("integer");
b1.Property<float>("Noise") b1.Property<int>("Noise")
.HasColumnType("real"); .HasColumnType("integer");
b1.Property<float>("RadiusBox") b1.Property<float>("RadiusBox")
.HasColumnType("real"); .HasColumnType("real");
@@ -535,7 +536,7 @@ namespace Moonlight.ApiServer.Database.Migrations
b1.HasKey("ThemeId"); b1.HasKey("ThemeId");
b1.ToTable("Core_Themes"); b1.ToTable("Themes", "core");
b1.ToJson("Content"); b1.ToJson("Content");

View File

@@ -26,7 +26,7 @@ public class ApiKeysController : Controller
[HttpGet] [HttpGet]
[Authorize(Policy = "permissions:admin.apikeys.get")] [Authorize(Policy = "permissions:admin.apikeys.get")]
public async Task<ActionResult<ICountedData<ApiKeyResponse>>> Get( public async Task<ActionResult<ICountedData<ApiKeyResponse>>> GetAsync(
[FromQuery] int startIndex, [FromQuery] int startIndex,
[FromQuery] int count, [FromQuery] int count,
[FromQuery] string? orderBy, [FromQuery] string? orderBy,
@@ -81,7 +81,7 @@ public class ApiKeysController : Controller
[HttpGet("{id:int}")] [HttpGet("{id:int}")]
[Authorize(Policy = "permissions:admin.apikeys.get")] [Authorize(Policy = "permissions:admin.apikeys.get")]
public async Task<ActionResult<ApiKeyResponse>> GetSingle(int id) public async Task<ActionResult<ApiKeyResponse>> GetSingleAsync(int id)
{ {
var apiKey = await ApiKeyRepository var apiKey = await ApiKeyRepository
.Get() .Get()
@@ -97,7 +97,7 @@ public class ApiKeysController : Controller
[HttpPost] [HttpPost]
[Authorize(Policy = "permissions:admin.apikeys.create")] [Authorize(Policy = "permissions:admin.apikeys.create")]
public async Task<CreateApiKeyResponse> Create([FromBody] CreateApiKeyRequest request) public async Task<CreateApiKeyResponse> CreateAsync([FromBody] CreateApiKeyRequest request)
{ {
var apiKey = ApiKeyMapper.ToApiKey(request); var apiKey = ApiKeyMapper.ToApiKey(request);
@@ -117,7 +117,7 @@ public class ApiKeysController : Controller
[HttpPatch("{id:int}")] [HttpPatch("{id:int}")]
[Authorize(Policy = "permissions:admin.apikeys.update")] [Authorize(Policy = "permissions:admin.apikeys.update")]
public async Task<ActionResult<ApiKeyResponse>> Update([FromRoute] int id, [FromBody] UpdateApiKeyRequest request) public async Task<ActionResult<ApiKeyResponse>> UpdateAsync([FromRoute] int id, [FromBody] UpdateApiKeyRequest request)
{ {
var apiKey = await ApiKeyRepository var apiKey = await ApiKeyRepository
.Get() .Get()
@@ -135,7 +135,7 @@ public class ApiKeysController : Controller
[HttpDelete("{id:int}")] [HttpDelete("{id:int}")]
[Authorize(Policy = "permissions:admin.apikeys.delete")] [Authorize(Policy = "permissions:admin.apikeys.delete")]
public async Task<ActionResult> Delete([FromRoute] int id) public async Task<ActionResult> DeleteAsync([FromRoute] int id)
{ {
var apiKey = await ApiKeyRepository var apiKey = await ApiKeyRepository
.Get() .Get()

View File

@@ -19,9 +19,9 @@ public class AdvancedController : Controller
[HttpGet("frontend")] [HttpGet("frontend")]
[Authorize(Policy = "permissions:admin.system.advanced.frontend")] [Authorize(Policy = "permissions:admin.system.advanced.frontend")]
public async Task Frontend() public async Task FrontendAsync()
{ {
var stream = await FrontendService.GenerateZip(); var stream = await FrontendService.GenerateZipAsync();
await Results.File(stream, fileDownloadName: "frontend.zip").ExecuteAsync(HttpContext); await Results.File(stream, fileDownloadName: "frontend.zip").ExecuteAsync(HttpContext);
} }
} }

View File

@@ -26,7 +26,7 @@ public class ThemesController : Controller
[HttpGet] [HttpGet]
[Authorize(Policy = "permissions:admin.system.customisation.themes.read")] [Authorize(Policy = "permissions:admin.system.customisation.themes.read")]
public async Task<ActionResult<ICountedData<ThemeResponse>>> Get( public async Task<ActionResult<ICountedData<ThemeResponse>>> GetAsync(
[FromQuery] int startIndex, [FromQuery] int startIndex,
[FromQuery] int count, [FromQuery] int count,
[FromQuery] string? orderBy, [FromQuery] string? orderBy,
@@ -81,7 +81,7 @@ public class ThemesController : Controller
[HttpGet("{id:int}")] [HttpGet("{id:int}")]
[Authorize(Policy = "permissions:admin.system.customisation.themes.read")] [Authorize(Policy = "permissions:admin.system.customisation.themes.read")]
public async Task<ActionResult<ThemeResponse>> GetSingle([FromRoute] int id) public async Task<ActionResult<ThemeResponse>> GetSingleAsync([FromRoute] int id)
{ {
var theme = await ThemeRepository var theme = await ThemeRepository
.Get() .Get()
@@ -97,7 +97,7 @@ public class ThemesController : Controller
[HttpPost] [HttpPost]
[Authorize(Policy = "permissions:admin.system.customisation.themes.write")] [Authorize(Policy = "permissions:admin.system.customisation.themes.write")]
public async Task<ActionResult<ThemeResponse>> Create([FromBody] CreateThemeRequest request) public async Task<ActionResult<ThemeResponse>> CreateAsync([FromBody] CreateThemeRequest request)
{ {
var theme = ThemeMapper.ToTheme(request); var theme = ThemeMapper.ToTheme(request);
@@ -108,7 +108,7 @@ public class ThemesController : Controller
[HttpPatch("{id:int}")] [HttpPatch("{id:int}")]
[Authorize(Policy = "permissions:admin.system.customisation.themes.write")] [Authorize(Policy = "permissions:admin.system.customisation.themes.write")]
public async Task<ActionResult<ThemeResponse>> Update([FromRoute] int id, [FromBody] UpdateThemeRequest request) public async Task<ActionResult<ThemeResponse>> UpdateAsync([FromRoute] int id, [FromBody] UpdateThemeRequest request)
{ {
var theme = await ThemeRepository var theme = await ThemeRepository
.Get() .Get()
@@ -141,7 +141,7 @@ public class ThemesController : Controller
[HttpDelete("{id:int}")] [HttpDelete("{id:int}")]
[Authorize(Policy = "permissions:admin.system.customisation.themes.write")] [Authorize(Policy = "permissions:admin.system.customisation.themes.write")]
public async Task<ActionResult> Delete([FromRoute] int id) public async Task<ActionResult> DeleteAsync([FromRoute] int id)
{ {
var theme = await ThemeRepository var theme = await ThemeRepository
.Get() .Get()

View File

@@ -21,7 +21,7 @@ public class DiagnoseController : Controller
} }
[HttpPost] [HttpPost]
public async Task<ActionResult> Diagnose([FromBody] GenerateDiagnoseRequest request) public async Task<ActionResult> DiagnoseAsync([FromBody] GenerateDiagnoseRequest request)
{ {
var stream = await DiagnoseService.GenerateDiagnoseAsync(request.Providers); var stream = await DiagnoseService.GenerateDiagnoseAsync(request.Providers);
@@ -29,7 +29,7 @@ public class DiagnoseController : Controller
} }
[HttpGet("providers")] [HttpGet("providers")]
public async Task<ActionResult<DiagnoseProvideResponse[]>> GetProviders() public async Task<ActionResult<DiagnoseProvideResponse[]>> GetProvidersAsync()
{ {
return await DiagnoseService.GetProvidersAsync(); return await DiagnoseService.GetProvidersAsync();
} }

View File

@@ -23,7 +23,7 @@ public class CombineController : Controller
} }
[HttpPost("combine")] [HttpPost("combine")]
public async Task<IResult> Combine([FromBody] CombineRequest request) public async Task<IResult> CombineAsync([FromBody] CombineRequest request)
{ {
// Validate file lenght // Validate file lenght
if (request.Files.Length < 2) if (request.Files.Length < 2)

View File

@@ -19,7 +19,7 @@ public class CompressController : Controller
private const string BaseDirectory = "storage"; private const string BaseDirectory = "storage";
[HttpPost("compress")] [HttpPost("compress")]
public async Task<IResult> Compress([FromBody] CompressRequest request) public async Task<IResult> CompressAsync([FromBody] CompressRequest request)
{ {
// Validate item length // Validate item length
if (request.Items.Length == 0) if (request.Items.Length == 0)
@@ -48,11 +48,11 @@ public class CompressController : Controller
switch (request.Format) switch (request.Format)
{ {
case "tar.gz": case "tar.gz":
await CompressTarGz(destinationPath, itemsPaths, rootPath); await CompressTarGzAsync(destinationPath, itemsPaths, rootPath);
break; break;
case "zip": case "zip":
await CompressZip(destinationPath, itemsPaths, rootPath); await CompressZipAsync(destinationPath, itemsPaths, rootPath);
break; break;
default: default:
@@ -66,14 +66,14 @@ public class CompressController : Controller
#region Tar Gz #region Tar Gz
private async Task CompressTarGz(string destination, IEnumerable<string> items, string root) private async Task CompressTarGzAsync(string destination, IEnumerable<string> items, string root)
{ {
await using var outStream = System.IO.File.Create(destination); await using var outStream = System.IO.File.Create(destination);
await using var gzoStream = new GZipOutputStream(outStream); await using var gzoStream = new GZipOutputStream(outStream);
await using var tarStream = new TarOutputStream(gzoStream, Encoding.UTF8); await using var tarStream = new TarOutputStream(gzoStream, Encoding.UTF8);
foreach (var item in items) foreach (var item in items)
await CompressItemToTarGz(tarStream, item, root); await CompressItemToTarGzAsync(tarStream, item, root);
await tarStream.FlushAsync(); await tarStream.FlushAsync();
await gzoStream.FlushAsync(); await gzoStream.FlushAsync();
@@ -84,7 +84,7 @@ public class CompressController : Controller
outStream.Close(); outStream.Close();
} }
private async Task CompressItemToTarGz(TarOutputStream tarOutputStream, string item, string root) private async Task CompressItemToTarGzAsync(TarOutputStream tarOutputStream, string item, string root)
{ {
if (System.IO.File.Exists(item)) if (System.IO.File.Exists(item))
{ {
@@ -117,7 +117,7 @@ public class CompressController : Controller
if (Directory.Exists(item)) if (Directory.Exists(item))
{ {
foreach (var fsEntry in Directory.EnumerateFileSystemEntries(item)) foreach (var fsEntry in Directory.EnumerateFileSystemEntries(item))
await CompressItemToTarGz(tarOutputStream, fsEntry, root); await CompressItemToTarGzAsync(tarOutputStream, fsEntry, root);
} }
} }
@@ -125,13 +125,13 @@ public class CompressController : Controller
#region ZIP #region ZIP
private async Task CompressZip(string destination, IEnumerable<string> items, string root) private async Task CompressZipAsync(string destination, IEnumerable<string> items, string root)
{ {
await using var outStream = System.IO.File.Create(destination); await using var outStream = System.IO.File.Create(destination);
await using var zipOutputStream = new ZipOutputStream(outStream); await using var zipOutputStream = new ZipOutputStream(outStream);
foreach (var item in items) foreach (var item in items)
await AddItemToZip(zipOutputStream, item, root); await AddItemToZipAsync(zipOutputStream, item, root);
await zipOutputStream.FlushAsync(); await zipOutputStream.FlushAsync();
await outStream.FlushAsync(); await outStream.FlushAsync();
@@ -140,7 +140,7 @@ public class CompressController : Controller
outStream.Close(); outStream.Close();
} }
private async Task AddItemToZip(ZipOutputStream outputStream, string item, string root) private async Task AddItemToZipAsync(ZipOutputStream outputStream, string item, string root)
{ {
if (System.IO.File.Exists(item)) if (System.IO.File.Exists(item))
{ {
@@ -175,7 +175,7 @@ public class CompressController : Controller
if (Directory.Exists(item)) if (Directory.Exists(item))
{ {
foreach (var subItem in Directory.EnumerateFileSystemEntries(item)) foreach (var subItem in Directory.EnumerateFileSystemEntries(item))
await AddItemToZip(outputStream, subItem, root); await AddItemToZipAsync(outputStream, subItem, root);
} }
} }

View File

@@ -17,7 +17,7 @@ public class DecompressController : Controller
private const string BaseDirectory = "storage"; private const string BaseDirectory = "storage";
[HttpPost("decompress")] [HttpPost("decompress")]
public async Task Decompress([FromBody] DecompressRequest request) public async Task DecompressAsync([FromBody] DecompressRequest request)
{ {
var path = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Path)); var path = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Path));
var destination = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Destination)); var destination = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(request.Destination));
@@ -25,18 +25,18 @@ public class DecompressController : Controller
switch (request.Format) switch (request.Format)
{ {
case "tar.gz": case "tar.gz":
await DecompressTarGz(path, destination); await DecompressTarGzAsync(path, destination);
break; break;
case "zip": case "zip":
await DecompressZip(path, destination); await DecompressZipAsync(path, destination);
break; break;
} }
} }
#region Tar Gz #region Tar Gz
private async Task DecompressTarGz(string path, string destination) private async Task DecompressTarGzAsync(string path, string destination)
{ {
await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
await using var gzipInputStream = new GZipInputStream(fs); await using var gzipInputStream = new GZipInputStream(fs);
@@ -74,7 +74,7 @@ public class DecompressController : Controller
#region Zip #region Zip
private async Task DecompressZip(string path, string destination) private async Task DecompressZipAsync(string path, string destination)
{ {
await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var fs = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
await using var zipInputStream = new ZipInputStream(fs); await using var zipInputStream = new ZipInputStream(fs);

View File

@@ -25,7 +25,7 @@ public class DownloadUrlController : Controller
} }
[HttpGet] [HttpGet]
public async Task Get([FromQuery] string path) public async Task GetAsync([FromQuery] string path)
{ {
var physicalPath = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(path)); var physicalPath = Path.Combine(BaseDirectory, FilePathHelper.SanitizePath(path));
var name = Path.GetFileName(physicalPath); var name = Path.GetFileName(physicalPath);
@@ -55,7 +55,7 @@ public class DownloadUrlController : Controller
await using var zipStream = new ZipOutputStream(Response.Body); await using var zipStream = new ZipOutputStream(Response.Body);
zipStream.IsStreamOwner = false; zipStream.IsStreamOwner = false;
await StreamFolderAsZip(zipStream, physicalPath, baseDirectory, HttpContext.RequestAborted); await StreamFolderAsZipAsync(zipStream, physicalPath, baseDirectory, HttpContext.RequestAborted);
} }
catch (ZipException) catch (ZipException)
{ {
@@ -68,7 +68,7 @@ public class DownloadUrlController : Controller
} }
} }
private async Task StreamFolderAsZip( private async Task StreamFolderAsZipAsync(
ZipOutputStream zipStream, ZipOutputStream zipStream,
string path, string rootPath, string path, string rootPath,
CancellationToken cancellationToken CancellationToken cancellationToken
@@ -102,7 +102,7 @@ public class DownloadUrlController : Controller
if (HttpContext.RequestAborted.IsCancellationRequested) if (HttpContext.RequestAborted.IsCancellationRequested)
return; return;
await StreamFolderAsZip(zipStream, directory, rootPath, cancellationToken); await StreamFolderAsZipAsync(zipStream, directory, rootPath, cancellationToken);
} }
} }
@@ -110,7 +110,7 @@ public class DownloadUrlController : Controller
// Yes I know we can just create that url on the client as the exist validation is done on both endpoints, // Yes I know we can just create that url on the client as the exist validation is done on both endpoints,
// but we leave it here for future modifications. E.g. using a distributed file provider or smth like that // but we leave it here for future modifications. E.g. using a distributed file provider or smth like that
[HttpPost] [HttpPost]
public Task<DownloadUrlResponse> Post([FromQuery] string path) public Task<DownloadUrlResponse> PostAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath); var physicalPath = Path.Combine(BaseDirectory, safePath);

View File

@@ -15,7 +15,7 @@ public class FilesController : Controller
private const string BaseDirectory = "storage"; private const string BaseDirectory = "storage";
[HttpPost("touch")] [HttpPost("touch")]
public async Task CreateFile([FromQuery] string path) public async Task CreateFileAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath); var physicalPath = Path.Combine(BaseDirectory, safePath);
@@ -31,7 +31,7 @@ public class FilesController : Controller
} }
[HttpPost("mkdir")] [HttpPost("mkdir")]
public Task CreateFolder([FromQuery] string path) public Task CreateFolderAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath); var physicalPath = Path.Combine(BaseDirectory, safePath);
@@ -47,7 +47,7 @@ public class FilesController : Controller
} }
[HttpGet("list")] [HttpGet("list")]
public Task<FileSystemEntryResponse[]> List([FromQuery] string path) public Task<FileSystemEntryResponse[]> ListAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath); var physicalPath = Path.Combine(BaseDirectory, safePath);
@@ -92,7 +92,7 @@ public class FilesController : Controller
} }
[HttpPost("move")] [HttpPost("move")]
public Task Move([FromQuery] string oldPath, [FromQuery] string newPath) public Task MoveAsync([FromQuery] string oldPath, [FromQuery] string newPath)
{ {
var oldSafePath = FilePathHelper.SanitizePath(oldPath); var oldSafePath = FilePathHelper.SanitizePath(oldPath);
var newSafePath = FilePathHelper.SanitizePath(newPath); var newSafePath = FilePathHelper.SanitizePath(newPath);
@@ -123,7 +123,7 @@ public class FilesController : Controller
} }
[HttpDelete("delete")] [HttpDelete("delete")]
public Task Delete([FromQuery] string path) public Task DeleteAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalDirPath = Path.Combine(BaseDirectory, safePath); var physicalDirPath = Path.Combine(BaseDirectory, safePath);
@@ -141,7 +141,7 @@ public class FilesController : Controller
} }
[HttpPost("upload")] [HttpPost("upload")]
public async Task<IResult> Upload([FromQuery] string path) public async Task<IResult> UploadAsync([FromQuery] string path)
{ {
if (Request.Form.Files.Count != 1) if (Request.Form.Files.Count != 1)
return Results.Problem("Only one file is allowed in the request", statusCode: 400); return Results.Problem("Only one file is allowed in the request", statusCode: 400);
@@ -179,7 +179,7 @@ public class FilesController : Controller
} }
[HttpGet("download")] [HttpGet("download")]
public async Task Download([FromQuery] string path) public async Task DownloadAsync([FromQuery] string path)
{ {
var safePath = FilePathHelper.SanitizePath(path); var safePath = FilePathHelper.SanitizePath(path);
var physicalPath = Path.Combine(BaseDirectory, safePath); var physicalPath = Path.Combine(BaseDirectory, safePath);

View File

@@ -18,7 +18,7 @@ public class HangfireController : Controller
} }
[HttpGet("stats")] [HttpGet("stats")]
public Task<HangfireStatsResponse> GetStats() public Task<HangfireStatsResponse> GetStatsAsync()
{ {
var statistics = JobStorage.GetMonitoringApi().GetStatistics(); var statistics = JobStorage.GetMonitoringApi().GetStatistics();

View File

@@ -18,21 +18,21 @@ public class SystemController : Controller
[HttpGet] [HttpGet]
[Authorize(Policy = "permissions:admin.system.overview")] [Authorize(Policy = "permissions:admin.system.overview")]
public async Task<SystemOverviewResponse> GetOverview() public async Task<SystemOverviewResponse> GetOverviewAsync()
{ {
return new() return new()
{ {
Uptime = await ApplicationService.GetUptime(), Uptime = await ApplicationService.GetUptimeAsync(),
CpuUsage = await ApplicationService.GetCpuUsage(), CpuUsage = await ApplicationService.GetCpuUsageAsync(),
MemoryUsage = await ApplicationService.GetMemoryUsage(), MemoryUsage = await ApplicationService.GetMemoryUsageAsync(),
OperatingSystem = await ApplicationService.GetOsName() OperatingSystem = await ApplicationService.GetOsNameAsync()
}; };
} }
[HttpPost("shutdown")] [HttpPost("shutdown")]
[Authorize(Policy = "permissions:admin.system.shutdown")] [Authorize(Policy = "permissions:admin.system.shutdown")]
public async Task Shutdown() public async Task ShutdownAsync()
{ {
await ApplicationService.Shutdown(); await ApplicationService.ShutdownAsync();
} }
} }

View File

@@ -27,7 +27,7 @@ public class UsersController : Controller
[HttpGet] [HttpGet]
[Authorize(Policy = "permissions:admin.users.get")] [Authorize(Policy = "permissions:admin.users.get")]
public async Task<ActionResult<ICountedData<UserResponse>>> Get( public async Task<ActionResult<ICountedData<UserResponse>>> GetAsync(
[FromQuery] int startIndex, [FromQuery] int startIndex,
[FromQuery] int count, [FromQuery] int count,
[FromQuery] string? orderBy, [FromQuery] string? orderBy,
@@ -83,7 +83,7 @@ public class UsersController : Controller
[HttpGet("{id}")] [HttpGet("{id}")]
[Authorize(Policy = "permissions:admin.users.get")] [Authorize(Policy = "permissions:admin.users.get")]
public async Task<ActionResult<UserResponse>> GetSingle(int id) public async Task<ActionResult<UserResponse>> GetSingleAsync(int id)
{ {
var user = await UserRepository var user = await UserRepository
.Get() .Get()
@@ -98,7 +98,7 @@ public class UsersController : Controller
[HttpPost] [HttpPost]
[Authorize(Policy = "permissions:admin.users.create")] [Authorize(Policy = "permissions:admin.users.create")]
public async Task<ActionResult<UserResponse>> Create([FromBody] CreateUserRequest request) public async Task<ActionResult<UserResponse>> CreateAsync([FromBody] CreateUserRequest request)
{ {
// Reformat values // Reformat values
request.Username = request.Username.ToLower().Trim(); request.Username = request.Username.ToLower().Trim();
@@ -128,7 +128,7 @@ public class UsersController : Controller
[HttpPatch("{id}")] [HttpPatch("{id}")]
[Authorize(Policy = "permissions:admin.users.update")] [Authorize(Policy = "permissions:admin.users.update")]
public async Task<ActionResult<UserResponse>> Update([FromRoute] int id, [FromBody] UpdateUserRequest request) public async Task<ActionResult<UserResponse>> UpdateAsync([FromRoute] int id, [FromBody] UpdateUserRequest request)
{ {
var user = await UserRepository var user = await UserRepository
.Get() .Get()
@@ -171,7 +171,7 @@ public class UsersController : Controller
[HttpDelete("{id}")] [HttpDelete("{id}")]
[Authorize(Policy = "permissions:admin.users.delete")] [Authorize(Policy = "permissions:admin.users.delete")]
public async Task<ActionResult> Delete([FromRoute] int id, [FromQuery] bool force = false) public async Task<ActionResult> DeleteAsync([FromRoute] int id, [FromQuery] bool force = false)
{ {
var user = await UserRepository var user = await UserRepository
.Get() .Get()
@@ -184,13 +184,13 @@ public class UsersController : Controller
if (!force) if (!force)
{ {
var validationResult = await deletionService.Validate(user); var validationResult = await deletionService.ValidateAsync(user);
if (!validationResult.IsAllowed) if (!validationResult.IsAllowed)
return Problem("Unable to delete user", statusCode: 400, title: validationResult.Reason); return Problem("Unable to delete user", statusCode: 400, title: validationResult.Reason);
} }
await deletionService.Delete(user, force); await deletionService.DeleteAsync(user, force);
return NoContent(); return NoContent();
} }
} }

View File

@@ -30,7 +30,7 @@ public class AuthController : Controller
} }
[HttpGet] [HttpGet]
public async Task<AuthSchemeResponse[]> GetSchemes() public async Task<AuthSchemeResponse[]> GetSchemesAsync()
{ {
var schemes = await SchemeProvider.GetAllSchemesAsync(); var schemes = await SchemeProvider.GetAllSchemesAsync();
@@ -47,7 +47,7 @@ public class AuthController : Controller
} }
[HttpGet("{identifier:alpha}")] [HttpGet("{identifier:alpha}")]
public async Task StartScheme([FromRoute] string identifier) public async Task StartSchemeAsync([FromRoute] string identifier)
{ {
// Validate identifier against our enable list // Validate identifier against our enable list
var allowedSchemes = Configuration.Authentication.EnabledSchemes; var allowedSchemes = Configuration.Authentication.EnabledSchemes;
@@ -91,7 +91,7 @@ public class AuthController : Controller
[Authorize] [Authorize]
[HttpGet("check")] [HttpGet("check")]
public async Task<AuthClaimResponse[]> Check() public async Task<AuthClaimResponse[]> CheckAsync()
{ {
var username = User.FindFirstValue(ClaimTypes.Name)!; var username = User.FindFirstValue(ClaimTypes.Name)!;
var id = User.FindFirstValue(ClaimTypes.NameIdentifier)!; var id = User.FindFirstValue(ClaimTypes.NameIdentifier)!;
@@ -113,7 +113,7 @@ public class AuthController : Controller
foreach (var extension in Extensions) foreach (var extension in Extensions)
{ {
claims.AddRange( claims.AddRange(
await extension.GetFrontendClaims(User) await extension.GetFrontendClaimsAsync(User)
); );
} }
@@ -121,7 +121,7 @@ public class AuthController : Controller
} }
[HttpGet("logout")] [HttpGet("logout")]
public async Task Logout() public async Task LogoutAsync()
{ {
await HttpContext.SignOutAsync(); await HttpContext.SignOutAsync();
await Results.Redirect("/").ExecuteAsync(HttpContext); await Results.Redirect("/").ExecuteAsync(HttpContext);

View File

@@ -18,13 +18,13 @@ public class FrontendController : Controller
} }
[HttpGet("frontend.json")] [HttpGet("frontend.json")]
public async Task<FrontendConfiguration> GetConfiguration() public async Task<FrontendConfiguration> GetConfigurationAsync()
=> await FrontendService.GetConfiguration(); => await FrontendService.GetConfigurationAsync();
[HttpGet] [HttpGet]
public async Task<IResult> Index() public async Task<IResult> IndexAsync()
{ {
var content = await FrontendService.GenerateIndexHtml(); var content = await FrontendService.GenerateIndexHtmlAsync();
return Results.Text(content, "text/html", Encoding.UTF8); return Results.Text(content, "text/html", Encoding.UTF8);
} }

View File

@@ -45,29 +45,29 @@ public class LocalAuthController : Controller
[HttpGet] [HttpGet]
[HttpGet("login")] [HttpGet("login")]
public async Task<IResult> Login() public async Task<ActionResult> LoginAsync()
{ {
var html = await ComponentHelper.RenderComponent<Login>(ServiceProvider); var html = await ComponentHelper.RenderToHtmlAsync<Login>(ServiceProvider);
return Results.Content(html, "text/html"); return Content(html, "text/html");
} }
[HttpGet("register")] [HttpGet("register")]
public async Task<IResult> Register() public async Task<ActionResult> RegisterAsync()
{ {
var html = await ComponentHelper.RenderComponent<Register>(ServiceProvider); var html = await ComponentHelper.RenderToHtmlAsync<Register>(ServiceProvider);
return Results.Content(html, "text/html"); return Content(html, "text/html");
} }
[HttpPost] [HttpPost]
[HttpPost("login")] [HttpPost("login")]
public async Task<IResult> Login([FromForm] string email, [FromForm] string password) public async Task<ActionResult> LoginAsync([FromForm] string email, [FromForm] string password)
{ {
try try
{ {
// Perform login // Perform login
var user = await InternalLogin(email, password); var user = await InternalLoginAsync(email, password);
// Login user // Login user
var options = Options.Get(LocalAuthConstants.AuthenticationScheme); var options = Options.Get(LocalAuthConstants.AuthenticationScheme);
@@ -84,34 +84,34 @@ public class LocalAuthController : Controller
), new AuthenticationProperties()); ), new AuthenticationProperties());
// Redirect back to wasm app // Redirect back to wasm app
return Results.Redirect("/"); return Redirect("/");
} }
catch (Exception e) catch (Exception e)
{ {
string errorMessage; string errorMessage;
if (e is HttpApiException apiException) if (e is AggregateException aggregateException)
errorMessage = apiException.Title; errorMessage = aggregateException.Message;
else else
{ {
errorMessage = "An internal error occured"; errorMessage = "An internal error occured";
Logger.LogError(e, "An unhandled error occured while logging in user"); Logger.LogError(e, "An unhandled error occured while logging in user");
} }
var html = await ComponentHelper.RenderComponent<Login>(ServiceProvider, var html = await ComponentHelper.RenderToHtmlAsync<Login>(ServiceProvider,
parameters => { parameters["ErrorMessage"] = errorMessage; }); parameters => { parameters["ErrorMessage"] = errorMessage; });
return Results.Content(html, "text/html"); return Content(html, "text/html");
} }
} }
[HttpPost("register")] [HttpPost("register")]
public async Task<IResult> Register([FromForm] string email, [FromForm] string password, [FromForm] string username) public async Task<ActionResult> RegisterAsync([FromForm] string email, [FromForm] string password, [FromForm] string username)
{ {
try try
{ {
// Perform register // Perform register
var user = await InternalRegister(username, email, password); var user = await InternalRegisterAsync(username, email, password);
// Login user // Login user
var options = Options.Get(LocalAuthConstants.AuthenticationScheme); var options = Options.Get(LocalAuthConstants.AuthenticationScheme);
@@ -128,37 +128,37 @@ public class LocalAuthController : Controller
), new AuthenticationProperties()); ), new AuthenticationProperties());
// Redirect back to wasm app // Redirect back to wasm app
return Results.Redirect("/"); return Redirect("/");
} }
catch (Exception e) catch (Exception e)
{ {
string errorMessage; string errorMessage;
if (e is HttpApiException apiException) if (e is AggregateException aggregateException)
errorMessage = apiException.Title; errorMessage = aggregateException.Message;
else else
{ {
errorMessage = "An internal error occured"; errorMessage = "An internal error occured";
Logger.LogError(e, "An unhandled error occured while logging in user"); Logger.LogError(e, "An unhandled error occured while logging in user");
} }
var html = await ComponentHelper.RenderComponent<Register>(ServiceProvider, var html = await ComponentHelper.RenderToHtmlAsync<Register>(ServiceProvider,
parameters => { parameters["ErrorMessage"] = errorMessage; }); parameters => { parameters["ErrorMessage"] = errorMessage; });
return Results.Content(html, "text/html"); return Content(html, "text/html");
} }
} }
private async Task<User> InternalRegister(string username, string email, string password) private async Task<User> InternalRegisterAsync(string username, string email, string password)
{ {
email = email.ToLower(); email = email.ToLower();
username = username.ToLower(); username = username.ToLower();
if (await UserRepository.Get().AnyAsync(x => x.Username == username)) if (await UserRepository.Get().AnyAsync(x => x.Username == username))
throw new HttpApiException("A account with that username already exists", 400); throw new AggregateException("A account with that username already exists");
if (await UserRepository.Get().AnyAsync(x => x.Email == email)) if (await UserRepository.Get().AnyAsync(x => x.Email == email))
throw new HttpApiException("A account with that email already exists", 400); throw new AggregateException("A account with that email already exists");
string[] permissions = []; string[] permissions = [];
@@ -185,7 +185,7 @@ public class LocalAuthController : Controller
return finalUser; return finalUser;
} }
private async Task<User> InternalLogin(string email, string password) private async Task<User> InternalLoginAsync(string email, string password)
{ {
email = email.ToLower(); email = email.ToLower();
@@ -194,10 +194,10 @@ public class LocalAuthController : Controller
.FirstOrDefaultAsync(x => x.Email == email); .FirstOrDefaultAsync(x => x.Email == email);
if (user == null) if (user == null)
throw new HttpApiException("Invalid combination of email and password", 400); throw new AggregateException("Invalid combination of email and password");
if (!HashHelper.Verify(password, user.Password)) if (!HashHelper.Verify(password, user.Password))
throw new HttpApiException("Invalid combination of email and password", 400); throw new AggregateException("Invalid combination of email and password");
return user; return user;
} }

View File

@@ -24,7 +24,7 @@ public class SwaggerController : Controller
[HttpGet] [HttpGet]
[Authorize] [Authorize]
public async Task<ActionResult> Get() public async Task<ActionResult> GetAsync()
{ {
if (!Configuration.Development.EnableApiDocs) if (!Configuration.Development.EnableApiDocs)
return BadRequest("Api docs are disabled"); return BadRequest("Api docs are disabled");
@@ -32,7 +32,7 @@ public class SwaggerController : Controller
var options = new ApiDocsOptions(); var options = new ApiDocsOptions();
var optionsJson = JsonSerializer.Serialize(options); var optionsJson = JsonSerializer.Serialize(options);
var html = await ComponentHelper.RenderComponent<SwaggerPage>( var html = await ComponentHelper.RenderToHtmlAsync<SwaggerPage>(
ServiceProvider, ServiceProvider,
parameters => parameters =>
{ {

View File

@@ -7,7 +7,7 @@ namespace Moonlight.ApiServer.Http.Hubs;
public class DiagnoseHub : Hub public class DiagnoseHub : Hub
{ {
[HubMethodName("Ping")] [HubMethodName("Ping")]
public async Task Ping() public async Task PingAsync()
{ {
await Clients.All.SendAsync("Pong"); await Clients.All.SendAsync("Pong");
} }

View File

@@ -11,7 +11,7 @@ public class ApplicationMetric : IMetric
private Gauge<int> CpuUsage; private Gauge<int> CpuUsage;
private Gauge<double> Uptime; private Gauge<double> Uptime;
public Task Initialize(Meter meter) public Task InitializeAsync(Meter meter)
{ {
MemoryUsage = meter.CreateGauge<long>("moonlight_memory_usage"); MemoryUsage = meter.CreateGauge<long>("moonlight_memory_usage");
CpuUsage = meter.CreateGauge<int>("moonlight_cpu_usage"); CpuUsage = meter.CreateGauge<int>("moonlight_cpu_usage");
@@ -20,17 +20,17 @@ public class ApplicationMetric : IMetric
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task Run(IServiceProvider provider, CancellationToken cancellationToken) public async Task RunAsync(IServiceProvider provider, CancellationToken cancellationToken)
{ {
var applicationService = provider.GetRequiredService<ApplicationService>(); var applicationService = provider.GetRequiredService<ApplicationService>();
var memory = await applicationService.GetMemoryUsage(); var memory = await applicationService.GetMemoryUsageAsync();
MemoryUsage.Record(memory); MemoryUsage.Record(memory);
var uptime = await applicationService.GetUptime(); var uptime = await applicationService.GetUptimeAsync();
Uptime.Record(uptime.TotalSeconds); Uptime.Record(uptime.TotalSeconds);
var cpu = await applicationService.GetCpuUsage(); var cpu = await applicationService.GetCpuUsageAsync();
CpuUsage.Record(cpu); CpuUsage.Record(cpu);
} }
} }

View File

@@ -11,14 +11,14 @@ public class UsersMetric : IMetric
{ {
private Gauge<int> Users; private Gauge<int> Users;
public Task Initialize(Meter meter) public Task InitializeAsync(Meter meter)
{ {
Users = meter.CreateGauge<int>("moonlight_users"); Users = meter.CreateGauge<int>("moonlight_users");
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task Run(IServiceProvider provider, CancellationToken cancellationToken) public async Task RunAsync(IServiceProvider provider, CancellationToken cancellationToken)
{ {
var usersRepo = provider.GetRequiredService<DatabaseRepository<User>>(); var usersRepo = provider.GetRequiredService<DatabaseRepository<User>>();
var count = await usersRepo.Get().CountAsync(cancellationToken: cancellationToken); var count = await usersRepo.Get().CountAsync(cancellationToken: cancellationToken);

View File

@@ -21,7 +21,7 @@ namespace Moonlight.ApiServer.Implementations.Startup;
public class CoreStartup : IPluginStartup public class CoreStartup : IPluginStartup
{ {
public Task BuildApplication(IServiceProvider serviceProvider, IHostApplicationBuilder builder) public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder)
{ {
var configuration = serviceProvider.GetRequiredService<AppConfiguration>(); var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
@@ -142,7 +142,7 @@ public class CoreStartup : IPluginStartup
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task ConfigureApplication(IServiceProvider serviceProvider, IApplicationBuilder app) public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app)
{ {
var configuration = serviceProvider.GetRequiredService<AppConfiguration>(); var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
@@ -156,7 +156,7 @@ public class CoreStartup : IPluginStartup
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task ConfigureEndpoints(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder) public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder)
{ {
var configuration = serviceProvider.GetRequiredService<AppConfiguration>(); var configuration = serviceProvider.GetRequiredService<AppConfiguration>();

View File

@@ -12,5 +12,5 @@ public interface IAuthCheckExtension
/// </summary> /// </summary>
/// <param name="principal">The principal of the current signed-in user</param> /// <param name="principal">The principal of the current signed-in user</param>
/// <returns>An array of claim responses which gets added to the list of claims to send to the frontend</returns> /// <returns>An array of claim responses which gets added to the list of claims to send to the frontend</returns>
public Task<AuthClaimResponse[]> GetFrontendClaims(ClaimsPrincipal principal); public Task<AuthClaimResponse[]> GetFrontendClaimsAsync(ClaimsPrincipal principal);
} }

View File

@@ -4,6 +4,6 @@ namespace Moonlight.ApiServer.Interfaces;
public interface IMetric public interface IMetric
{ {
public Task Initialize(Meter meter); public Task InitializeAsync(Meter meter);
public Task Run(IServiceProvider provider, CancellationToken cancellationToken); public Task RunAsync(IServiceProvider provider, CancellationToken cancellationToken);
} }

View File

@@ -12,7 +12,7 @@ public interface IUserAuthExtension
/// <param name="user">The current user this method is called for</param> /// <param name="user">The current user this method is called for</param>
/// <param name="principal">The principal after being processed by moonlight itself</param> /// <param name="principal">The principal after being processed by moonlight itself</param>
/// <returns>The result of the synchronisation. Returning false will immediately invalidate the sign-in and no other extensions will be called</returns> /// <returns>The result of the synchronisation. Returning false will immediately invalidate the sign-in and no other extensions will be called</returns>
public Task<bool> Sync(User user, ClaimsPrincipal principal); public Task<bool> SyncAsync(User user, ClaimsPrincipal principal);
/// <summary> /// <summary>
/// IMPORTANT: Please note that heavy operations should not occur in this method as it will be called for every request /// IMPORTANT: Please note that heavy operations should not occur in this method as it will be called for every request
@@ -21,5 +21,5 @@ public interface IUserAuthExtension
/// <param name="user">The current user this method is called for</param> /// <param name="user">The current user this method is called for</param>
/// <param name="principal">The principal after being processed by moonlight itself</param> /// <param name="principal">The principal after being processed by moonlight itself</param>
/// <returns>The result of the validation. Returning false will immediately invalidate the users session and no other extensions will be called</returns> /// <returns>The result of the validation. Returning false will immediately invalidate the users session and no other extensions will be called</returns>
public Task<bool> Validate(User user, ClaimsPrincipal principal); public Task<bool> ValidateAsync(User user, ClaimsPrincipal principal);
} }

View File

@@ -5,6 +5,6 @@ namespace Moonlight.ApiServer.Interfaces;
public interface IUserDeleteHandler public interface IUserDeleteHandler
{ {
public Task<UserDeleteValidationResult> Validate(User user); public Task<UserDeleteValidationResult> ValidateAsync(User user);
public Task Delete(User user, bool force); public Task DeleteAsync(User user, bool force);
} }

View File

@@ -27,9 +27,10 @@
<PackageReference Include="Hangfire.EntityFrameworkCore" Version="0.7.0"/> <PackageReference Include="Hangfire.EntityFrameworkCore" Version="0.7.0"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.9" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.9" />
<PackageReference Include="MoonCore" Version="1.9.9" /> <PackageReference Include="MoonCore" Version="2.0.0" />
<PackageReference Include="MoonCore.Extended" Version="1.3.8" /> <PackageReference Include="MoonCore.Extended" Version="1.3.9" />
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2"/> <PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1"/> <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1"/>
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0"/> <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0"/>

View File

@@ -6,7 +6,7 @@ namespace Moonlight.ApiServer.Plugins;
public interface IPluginStartup public interface IPluginStartup
{ {
public Task BuildApplication(IServiceProvider serviceProvider, IHostApplicationBuilder builder); public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder);
public Task ConfigureApplication(IServiceProvider serviceProvider, IApplicationBuilder app); public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app);
public Task ConfigureEndpoints(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder); public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder);
} }

View File

@@ -14,7 +14,7 @@ public class ApiKeyAuthService
ApiKeyRepository = apiKeyRepository; ApiKeyRepository = apiKeyRepository;
} }
public async Task<bool> Validate(ClaimsPrincipal? principal) public async Task<bool> ValidateAsync(ClaimsPrincipal? principal)
{ {
// Ignore malformed claims principal // Ignore malformed claims principal
if (principal is not { Identity.IsAuthenticated: true }) if (principal is not { Identity.IsAuthenticated: true })

View File

@@ -19,7 +19,7 @@ public class ApplicationService
Host = host; Host = host;
} }
public Task<string> GetOsName() public Task<string> GetOsNameAsync()
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
@@ -58,7 +58,7 @@ public class ApplicationService
return Task.FromResult("N/A"); return Task.FromResult("N/A");
} }
public async Task<long> GetMemoryUsage() public async Task<long> GetMemoryUsageAsync()
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
@@ -87,14 +87,14 @@ public class ApplicationService
} }
} }
public Task<TimeSpan> GetUptime() public Task<TimeSpan> GetUptimeAsync()
{ {
var process = Process.GetCurrentProcess(); var process = Process.GetCurrentProcess();
var uptime = DateTime.Now - process.StartTime; var uptime = DateTime.Now - process.StartTime;
return Task.FromResult(uptime); return Task.FromResult(uptime);
} }
public Task<int> GetCpuUsage() public Task<int> GetCpuUsageAsync()
{ {
var process = Process.GetCurrentProcess(); var process = Process.GetCurrentProcess();
var cpuTime = process.TotalProcessorTime; var cpuTime = process.TotalProcessorTime;
@@ -105,7 +105,7 @@ public class ApplicationService
return Task.FromResult(cpuUsage); return Task.FromResult(cpuUsage);
} }
public Task Shutdown() public Task ShutdownAsync()
{ {
Logger.LogCritical("Restart of api server has been requested"); Logger.LogCritical("Restart of api server has been requested");

View File

@@ -40,7 +40,7 @@ public class FrontendService
ThemeRepository = themeRepository; ThemeRepository = themeRepository;
} }
public Task<FrontendConfiguration> GetConfiguration() public Task<FrontendConfiguration> GetConfigurationAsync()
{ {
var configuration = new FrontendConfiguration() var configuration = new FrontendConfiguration()
{ {
@@ -51,7 +51,7 @@ public class FrontendService
return Task.FromResult(configuration); return Task.FromResult(configuration);
} }
public async Task<string> GenerateIndexHtml() // TODO: Cache public async Task<string> GenerateIndexHtmlAsync() // TODO: Cache
{ {
// Load requested theme // Load requested theme
var theme = await ThemeRepository var theme = await ThemeRepository
@@ -70,7 +70,7 @@ public class FrontendService
.Distinct() .Distinct()
.ToArray(); .ToArray();
return await ComponentHelper.RenderComponent<FrontendPage>( return await ComponentHelper.RenderToHtmlAsync<FrontendPage>(
ServiceProvider, ServiceProvider,
parameters => parameters =>
{ {
@@ -82,7 +82,7 @@ public class FrontendService
); );
} }
public async Task<Stream> GenerateZip() // TODO: Rework to be able to extract everything successfully public async Task<Stream> GenerateZipAsync() // TODO: Rework to be able to extract everything successfully
{ {
// We only allow the access to this function when we are actually hosting the frontend // We only allow the access to this function when we are actually hosting the frontend
if (!Configuration.Frontend.EnableHosting) if (!Configuration.Frontend.EnableHosting)
@@ -109,16 +109,16 @@ public class FrontendService
var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true); var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
// Add wasm application // Add wasm application
await ArchiveFsItem(zipArchive, wasmPath, wasmPath); await ArchiveFsItemAsync(zipArchive, wasmPath, wasmPath);
// Add blazor files // Add blazor files
await ArchiveFsItem(zipArchive, blazorPath, blazorPath, "_framework/"); await ArchiveFsItemAsync(zipArchive, blazorPath, blazorPath, "_framework/");
// Add frontend.json // Add frontend.json
var frontendConfig = await GetConfiguration(); var frontendConfig = await GetConfigurationAsync();
frontendConfig.HostEnvironment = "Static"; frontendConfig.HostEnvironment = "Static";
var frontendJson = JsonSerializer.Serialize(frontendConfig); var frontendJson = JsonSerializer.Serialize(frontendConfig);
await ArchiveText(zipArchive, "frontend.json", frontendJson); await ArchiveTextAsync(zipArchive, "frontend.json", frontendJson);
// Finish zip archive and reset stream so the code calling this function can process it // Finish zip archive and reset stream so the code calling this function can process it
zipArchive.Dispose(); zipArchive.Dispose();
@@ -128,7 +128,7 @@ public class FrontendService
return memoryStream; return memoryStream;
} }
private async Task ArchiveFsItem(ZipArchive archive, string path, string prefixToRemove, string prefixToAdd = "") private async Task ArchiveFsItemAsync(ZipArchive archive, string path, string prefixToRemove, string prefixToAdd = "")
{ {
if (File.Exists(path)) if (File.Exists(path))
{ {
@@ -147,17 +147,17 @@ public class FrontendService
else else
{ {
foreach (var directoryItem in Directory.EnumerateFileSystemEntries(path)) foreach (var directoryItem in Directory.EnumerateFileSystemEntries(path))
await ArchiveFsItem(archive, directoryItem, prefixToRemove, prefixToAdd); await ArchiveFsItemAsync(archive, directoryItem, prefixToRemove, prefixToAdd);
} }
} }
private async Task ArchiveText(ZipArchive archive, string path, string content) private async Task ArchiveTextAsync(ZipArchive archive, string path, string content)
{ {
var data = Encoding.UTF8.GetBytes(content); var data = Encoding.UTF8.GetBytes(content);
await ArchiveBytes(archive, path, data); await ArchiveBytesAsync(archive, path, data);
} }
private async Task ArchiveBytes(ZipArchive archive, string path, byte[] bytes) private async Task ArchiveBytesAsync(ZipArchive archive, string path, byte[] bytes)
{ {
var entry = archive.CreateEntry(path); var entry = archive.CreateEntry(path);
await using var dataStream = entry.Open(); await using var dataStream = entry.Open();

View File

@@ -33,7 +33,7 @@ public class MetricsBackgroundService : BackgroundService
Metrics = metrics.ToArray(); Metrics = metrics.ToArray();
} }
private async Task Initialize() private async Task InitializeAsync()
{ {
Logger.LogDebug( Logger.LogDebug(
"Initializing metrics: {names}", "Initializing metrics: {names}",
@@ -41,12 +41,12 @@ public class MetricsBackgroundService : BackgroundService
); );
foreach (var metric in Metrics) foreach (var metric in Metrics)
await metric.Initialize(Meter); await metric.InitializeAsync(Meter);
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await Initialize(); await InitializeAsync();
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
@@ -56,7 +56,7 @@ public class MetricsBackgroundService : BackgroundService
{ {
try try
{ {
await metric.Run(scope.ServiceProvider, stoppingToken); await metric.RunAsync(scope.ServiceProvider, stoppingToken);
} }
catch (TaskCanceledException) catch (TaskCanceledException)
{ {

View File

@@ -33,7 +33,7 @@ public class UserAuthService
Extensions = extensions; Extensions = extensions;
} }
public async Task<bool> Sync(ClaimsPrincipal? principal) public async Task<bool> SyncAsync(ClaimsPrincipal? principal)
{ {
// Ignore malformed claims principal // Ignore malformed claims principal
if (principal is not { Identity.IsAuthenticated: true }) if (principal is not { Identity.IsAuthenticated: true })
@@ -107,7 +107,7 @@ public class UserAuthService
// Call extensions // Call extensions
foreach (var extension in Extensions) foreach (var extension in Extensions)
{ {
var result = await extension.Sync(user, principal); var result = await extension.SyncAsync(user, principal);
if (!result) // Exit immediately if result is false if (!result) // Exit immediately if result is false
return false; return false;
@@ -116,7 +116,7 @@ public class UserAuthService
return true; return true;
} }
public async Task<bool> Validate(ClaimsPrincipal? principal) public async Task<bool> ValidateAsync(ClaimsPrincipal? principal)
{ {
// Ignore malformed claims principal // Ignore malformed claims principal
if (principal is not { Identity.IsAuthenticated: true }) if (principal is not { Identity.IsAuthenticated: true })
@@ -157,7 +157,7 @@ public class UserAuthService
// Call extensions // Call extensions
foreach (var extension in Extensions) foreach (var extension in Extensions)
{ {
var result = await extension.Validate(user, principal); var result = await extension.ValidateAsync(user, principal);
if (!result) // Exit immediately if result is false if (!result) // Exit immediately if result is false
return false; return false;

View File

@@ -19,11 +19,11 @@ public class UserDeletionService
Handlers = handlers.ToArray(); Handlers = handlers.ToArray();
} }
public async Task<UserDeleteValidationResult> Validate(User user) public async Task<UserDeleteValidationResult> ValidateAsync(User user)
{ {
foreach (var handler in Handlers) foreach (var handler in Handlers)
{ {
var result = await handler.Validate(user); var result = await handler.ValidateAsync(user);
if (!result.IsAllowed) if (!result.IsAllowed)
return result; return result;
@@ -32,10 +32,10 @@ public class UserDeletionService
return UserDeleteValidationResult.Allow(); return UserDeleteValidationResult.Allow();
} }
public async Task Delete(User user, bool force) public async Task DeleteAsync(User user, bool force)
{ {
foreach (var handler in Handlers) foreach (var handler in Handlers)
await handler.Delete(user, force); await handler.DeleteAsync(user, force);
await UserRepository.RemoveAsync(user); await UserRepository.RemoveAsync(user);
} }

View File

@@ -13,7 +13,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterAuth() private Task RegisterAuthAsync()
{ {
WebApplicationBuilder.Services WebApplicationBuilder.Services
.AddAuthentication(options => { options.DefaultScheme = "MainScheme"; }) .AddAuthentication(options => { options.DefaultScheme = "MainScheme"; })
@@ -62,7 +62,7 @@ public partial class Startup
.RequestServices .RequestServices
.GetRequiredService<ApiKeyAuthService>(); .GetRequiredService<ApiKeyAuthService>();
var result = await apiKeyAuthService.Validate(context.Principal); var result = await apiKeyAuthService.ValidateAsync(context.Principal);
if (!result) if (!result)
context.Fail("API key has been deleted"); context.Fail("API key has been deleted");
@@ -120,7 +120,7 @@ public partial class Startup
.RequestServices .RequestServices
.GetRequiredService<UserAuthService>(); .GetRequiredService<UserAuthService>();
var result = await userSyncService.Sync(context.Principal); var result = await userSyncService.SyncAsync(context.Principal);
if (!result) if (!result)
context.Principal = new(); context.Principal = new();
@@ -135,7 +135,7 @@ public partial class Startup
.RequestServices .RequestServices
.GetRequiredService<UserAuthService>(); .GetRequiredService<UserAuthService>();
var result = await userSyncService.Validate(context.Principal); var result = await userSyncService.ValidateAsync(context.Principal);
if (!result) if (!result)
context.RejectPrincipal(); context.RejectPrincipal();
@@ -178,7 +178,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task UseAuth() private Task UseAuthAsync()
{ {
WebApplication.UseAuthentication(); WebApplication.UseAuthentication();

View File

@@ -9,7 +9,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterBase() private Task RegisterBaseAsync()
{ {
WebApplicationBuilder.Services.AutoAddServices<Startup>(); WebApplicationBuilder.Services.AutoAddServices<Startup>();
WebApplicationBuilder.Services.AddHttpClient(); WebApplicationBuilder.Services.AddHttpClient();
@@ -29,7 +29,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task UseBase() private Task UseBaseAsync()
{ {
WebApplication.UseRouting(); WebApplication.UseRouting();
WebApplication.UseExceptionHandler(); WebApplication.UseExceptionHandler();
@@ -37,7 +37,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task MapBase() private Task MapBaseAsync()
{ {
WebApplication.MapControllers(); WebApplication.MapControllers();
@@ -47,7 +47,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task ConfigureKestrel() private Task ConfigureKestrelAsync()
{ {
WebApplicationBuilder.WebHost.ConfigureKestrel(kestrelOptions => WebApplicationBuilder.WebHost.ConfigureKestrel(kestrelOptions =>
{ {

View File

@@ -8,11 +8,11 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private async Task SetupAppConfiguration() private async Task SetupAppConfigurationAsync()
{ {
var configPath = Path.Combine("storage", "config.yml"); var configPath = Path.Combine("storage", "config.yml");
await YamlDefaultGenerator.Generate<AppConfiguration>(configPath); await YamlDefaultGenerator.GenerateAsync<AppConfiguration>(configPath);
// Configure configuration (wow) // Configure configuration (wow)
var configurationBuilder = new ConfigurationBuilder(); var configurationBuilder = new ConfigurationBuilder();
@@ -27,7 +27,7 @@ public partial class Startup
configurationRoot.Bind(Configuration); configurationRoot.Bind(Configuration);
} }
private Task RegisterAppConfiguration() private Task RegisterAppConfigurationAsync()
{ {
WebApplicationBuilder.Services.AddSingleton(Configuration); WebApplicationBuilder.Services.AddSingleton(Configuration);
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -6,7 +6,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterDatabase() private Task RegisterDatabaseAsync()
{ {
WebApplicationBuilder.Services.AddDatabaseMappings(); WebApplicationBuilder.Services.AddDatabaseMappings();
WebApplicationBuilder.Services.AddServiceCollectionAccessor(); WebApplicationBuilder.Services.AddServiceCollectionAccessor();
@@ -16,9 +16,9 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task PrepareDatabase() private async Task PrepareDatabaseAsync()
{ {
await WebApplication.Services.EnsureDatabaseMigrated(); await WebApplication.Services.EnsureDatabaseMigratedAsync();
WebApplication.Services.GenerateDatabaseMappings(); WebApplication.Services.GenerateDatabaseMappings();
} }

View File

@@ -9,7 +9,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterHangfire() private Task RegisterHangfireAsync()
{ {
WebApplicationBuilder.Services.AddHangfire((provider, configuration) => WebApplicationBuilder.Services.AddHangfire((provider, configuration) =>
{ {
@@ -38,7 +38,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task UseHangfire() private Task UseHangfireAsync()
{ {
if (WebApplication.Environment.IsDevelopment()) if (WebApplication.Environment.IsDevelopment())
WebApplication.UseHangfireDashboard(); WebApplication.UseHangfireDashboard();

View File

@@ -6,7 +6,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task SetupLogging() private Task SetupLoggingAsync()
{ {
var loggerFactory = new LoggerFactory(); var loggerFactory = new LoggerFactory();
loggerFactory.AddAnsiConsole(); loggerFactory.AddAnsiConsole();
@@ -16,7 +16,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task RegisterLogging() private async Task RegisterLoggingAsync()
{ {
// Configure application logging // Configure application logging
WebApplicationBuilder.Logging.ClearProviders(); WebApplicationBuilder.Logging.ClearProviders();

View File

@@ -6,7 +6,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
private Task PrintVersion() private Task PrintVersionAsync()
{ {
// Fancy start console output... yes very fancy :> // Fancy start console output... yes very fancy :>
var rainbow = new Crayon.Rainbow(0.5); var rainbow = new Crayon.Rainbow(0.5);
@@ -25,7 +25,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task CreateStorage() private Task CreateStorageAsync()
{ {
Directory.CreateDirectory("storage"); Directory.CreateDirectory("storage");
Directory.CreateDirectory(Path.Combine("storage", "logs")); Directory.CreateDirectory(Path.Combine("storage", "logs"));
@@ -33,7 +33,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task RegisterCors() private Task RegisterCorsAsync()
{ {
var allowedOrigins = Configuration.Kestrel.AllowedOrigins; var allowedOrigins = Configuration.Kestrel.AllowedOrigins;
@@ -64,7 +64,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task UseCors() private Task UseCorsAsync()
{ {
WebApplication.UseCors(); WebApplication.UseCors();

View File

@@ -10,7 +10,7 @@ public partial class Startup
private IServiceProvider PluginLoadServiceProvider; private IServiceProvider PluginLoadServiceProvider;
private IPluginStartup[] PluginStartups; private IPluginStartup[] PluginStartups;
private Task InitializePlugins() private Task InitializePluginsAsync()
{ {
// Create service provider for starting up // Create service provider for starting up
var serviceCollection = new ServiceCollection(); var serviceCollection = new ServiceCollection();
@@ -28,13 +28,13 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task HookPluginBuild() private async Task HookPluginBuildAsync()
{ {
foreach (var pluginAppStartup in PluginStartups) foreach (var pluginAppStartup in PluginStartups)
{ {
try try
{ {
await pluginAppStartup.BuildApplication(PluginLoadServiceProvider, WebApplicationBuilder); await pluginAppStartup.BuildApplicationAsync(PluginLoadServiceProvider, WebApplicationBuilder);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -47,13 +47,13 @@ public partial class Startup
} }
} }
private async Task HookPluginConfigure() private async Task HookPluginConfigureAsync()
{ {
foreach (var pluginAppStartup in PluginStartups) foreach (var pluginAppStartup in PluginStartups)
{ {
try try
{ {
await pluginAppStartup.ConfigureApplication(PluginLoadServiceProvider, WebApplication); await pluginAppStartup.ConfigureApplicationAsync(PluginLoadServiceProvider, WebApplication);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -66,13 +66,13 @@ public partial class Startup
} }
} }
private async Task HookPluginEndpoints() private async Task HookPluginEndpointsAsync()
{ {
foreach (var pluginEndpointStartup in PluginStartups) foreach (var pluginEndpointStartup in PluginStartups)
{ {
try try
{ {
await pluginEndpointStartup.ConfigureEndpoints(PluginLoadServiceProvider, WebApplication); await pluginEndpointStartup.ConfigureEndpointsAsync(PluginLoadServiceProvider, WebApplication);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -6,7 +6,7 @@ namespace Moonlight.ApiServer.Startup;
public partial class Startup public partial class Startup
{ {
public Task RegisterSignalR() public Task RegisterSignalRAsync()
{ {
var signalRBuilder = WebApplicationBuilder.Services.AddSignalR(); var signalRBuilder = WebApplicationBuilder.Services.AddSignalR();
@@ -16,7 +16,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task MapSignalR() public Task MapSignalRAsync()
{ {
WebApplication.MapHub<DiagnoseHub>("/api/admin/system/diagnose/ws"); WebApplication.MapHub<DiagnoseHub>("/api/admin/system/diagnose/ws");

View File

@@ -19,7 +19,7 @@ public partial class Startup
public WebApplication WebApplication { get; private set; } public WebApplication WebApplication { get; private set; }
public WebApplicationBuilder WebApplicationBuilder { get; private set; } public WebApplicationBuilder WebApplicationBuilder { get; private set; }
public Task Initialize(string[] args, IPluginStartup[]? plugins = null) public Task InitializeAsync(string[] args, IPluginStartup[]? plugins = null)
{ {
Args = args; Args = args;
PluginStartups = plugins ?? []; PluginStartups = plugins ?? [];
@@ -27,43 +27,43 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task AddMoonlight(WebApplicationBuilder builder) public async Task AddMoonlightAsync(WebApplicationBuilder builder)
{ {
WebApplicationBuilder = builder; WebApplicationBuilder = builder;
await PrintVersion(); await PrintVersionAsync();
await CreateStorage(); await CreateStorageAsync();
await SetupAppConfiguration(); await SetupAppConfigurationAsync();
await SetupLogging(); await SetupLoggingAsync();
await InitializePlugins(); await InitializePluginsAsync();
await ConfigureKestrel(); await ConfigureKestrelAsync();
await RegisterAppConfiguration(); await RegisterAppConfigurationAsync();
await RegisterLogging(); await RegisterLoggingAsync();
await RegisterBase(); await RegisterBaseAsync();
await RegisterDatabase(); await RegisterDatabaseAsync();
await RegisterAuth(); await RegisterAuthAsync();
await RegisterCors(); await RegisterCorsAsync();
await RegisterHangfire(); await RegisterHangfireAsync();
await RegisterSignalR(); await RegisterSignalRAsync();
await HookPluginBuild(); await HookPluginBuildAsync();
} }
public async Task AddMoonlight(WebApplication application) public async Task AddMoonlightAsync(WebApplication application)
{ {
WebApplication = application; WebApplication = application;
await PrepareDatabase(); await PrepareDatabaseAsync();
await UseCors(); await UseCorsAsync();
await UseBase(); await UseBaseAsync();
await UseAuth(); await UseAuthAsync();
await UseHangfire(); await UseHangfireAsync();
await HookPluginConfigure(); await HookPluginConfigureAsync();
await MapBase(); await MapBaseAsync();
await MapSignalR(); await MapSignalRAsync();
await HookPluginEndpoints(); await HookPluginEndpointsAsync();
} }
} }

View File

@@ -15,8 +15,8 @@
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.8" /> <PackageReference Include="MoonCore.PluginFramework" Version="1.0.8" />
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2" /> <PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.8" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.9" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
<Import Project="Plugins.props" /> <Import Project="Plugins.props" />

View File

@@ -7,14 +7,14 @@ pluginLoader.Initialize();
var startup = new Startup(); var startup = new Startup();
await startup.Initialize(pluginLoader.Instances); await startup.InitializeAsync(pluginLoader.Instances);
var wasmHostBuilder = WebAssemblyHostBuilder.CreateDefault(args); var wasmHostBuilder = WebAssemblyHostBuilder.CreateDefault(args);
await startup.AddMoonlight(wasmHostBuilder); await startup.AddMoonlightAsync(wasmHostBuilder);
var wasmApp = wasmHostBuilder.Build(); var wasmApp = wasmHostBuilder.Build();
await startup.AddMoonlight(wasmApp); await startup.AddMoonlightAsync(wasmApp);
await wasmApp.RunAsync(); await wasmApp.RunAsync();

View File

@@ -114,4 +114,24 @@
.dropdown-menu { .dropdown-menu {
@apply bg-base-150; @apply bg-base-150;
} }
.advance-select-menu {
@apply !border-base-content/20 border-2 ring-0! outline-0! bg-base-200/50 !px-0;
}
.advance-select-option {
@apply !rounded-none hover:!bg-primary;
}
.advance-select-option.selected {
@apply !bg-primary !text-primary-content;
}
.advance-select-toggle {
@apply !border-base-content/20 border-2 ring-0! outline-0! focus:border-primary! focus-within:border-primary! bg-base-200/50;
}
.table thead {
@apply !normal-case;
}
} }

View File

@@ -7,7 +7,7 @@ namespace Moonlight.Client.Implementations;
public class CoreStartup : IPluginStartup public class CoreStartup : IPluginStartup
{ {
public Task BuildApplication(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder) public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder)
{ {
builder.Services.AddSingleton<ISidebarItemProvider, DefaultSidebarItemProvider>(); builder.Services.AddSingleton<ISidebarItemProvider, DefaultSidebarItemProvider>();
builder.Services.AddSingleton<IOverviewElementProvider, DefaultOverviewElementProvider>(); builder.Services.AddSingleton<IOverviewElementProvider, DefaultOverviewElementProvider>();
@@ -15,6 +15,6 @@ public class CoreStartup : IPluginStartup
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task ConfigureApplication(IServiceProvider serviceProvider, WebAssemblyHost app) public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app)
=> Task.CompletedTask; => Task.CompletedTask;
} }

View File

@@ -11,7 +11,7 @@ public class LogErrorFilter : IGlobalErrorFilter
Logger = logger; Logger = logger;
} }
public Task<bool> HandleException(Exception ex) public Task<bool> HandleExceptionAsync(Exception ex)
{ {
Logger.LogError(ex, "Global error processed"); Logger.LogError(ex, "Global error processed");
return Task.FromResult(false); return Task.FromResult(false);

View File

@@ -18,21 +18,21 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
ApiClient = apiClient; ApiClient = apiClient;
} }
public async Task CreateFile(string path) public async Task CreateFileAsync(string path)
{ {
await ApiClient.Post( await ApiClient.Post(
$"{BaseApiUrl}/touch?path={path}" $"{BaseApiUrl}/touch?path={path}"
); );
} }
public async Task CreateDirectory(string path) public async Task CreateDirectoryAsync(string path)
{ {
await ApiClient.Post( await ApiClient.Post(
$"{BaseApiUrl}/mkdir?path={path}" $"{BaseApiUrl}/mkdir?path={path}"
); );
} }
public async Task<FsEntry[]> List(string path) public async Task<FsEntry[]> ListAsync(string path)
{ {
var entries = await ApiClient.GetJson<FileSystemEntryResponse[]>( var entries = await ApiClient.GetJson<FileSystemEntryResponse[]>(
$"{BaseApiUrl}/list?path={path}" $"{BaseApiUrl}/list?path={path}"
@@ -48,14 +48,14 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
}).ToArray(); }).ToArray();
} }
public async Task Move(string oldPath, string newPath) public async Task MoveAsync(string oldPath, string newPath)
{ {
await ApiClient.Post( await ApiClient.Post(
$"{BaseApiUrl}/move?oldPath={oldPath}&newPath={newPath}" $"{BaseApiUrl}/move?oldPath={oldPath}&newPath={newPath}"
); );
} }
public async Task Read(string path, Func<Stream, Task> onHandleData) public async Task ReadAsync(string path, Func<Stream, Task> onHandleData)
{ {
await using var stream = await ApiClient.GetStream( await using var stream = await ApiClient.GetStream(
$"{BaseApiUrl}/download?path={path}" $"{BaseApiUrl}/download?path={path}"
@@ -66,7 +66,7 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
stream.Close(); stream.Close();
} }
public async Task Write(string path, Stream dataStream) public async Task WriteAsync(string path, Stream dataStream)
{ {
using var multiPartForm = new MultipartFormDataContent(); using var multiPartForm = new MultipartFormDataContent();
@@ -78,14 +78,14 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
); );
} }
public async Task Delete(string path) public async Task DeleteAsync(string path)
{ {
await ApiClient.Delete( await ApiClient.Delete(
$"{BaseApiUrl}/delete?path={path}" $"{BaseApiUrl}/delete?path={path}"
); );
} }
public async Task Combine(string destination, string[] files) public async Task CombineAsync(string destination, string[] files)
{ {
await ApiClient.Post( await ApiClient.Post(
$"{BaseApiUrl}/combine", $"{BaseApiUrl}/combine",
@@ -103,7 +103,7 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
new("tar.gz", ["tar.gz"], "Tar.gz Archive") new("tar.gz", ["tar.gz"], "Tar.gz Archive")
]; ];
public async Task Archive( public async Task ArchiveAsync(
string destination, string destination,
ArchiveFormat format, ArchiveFormat format,
string root, string root,
@@ -120,7 +120,7 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
}); });
} }
public async Task Unarchive( public async Task UnarchiveAsync(
string path, string path,
ArchiveFormat format, ArchiveFormat format,
string destination, string destination,
@@ -137,13 +137,13 @@ public class SystemFsAccess : IFsAccess, ICombineAccess, IArchiveAccess, IDownlo
); );
} }
public async Task<string> GetFileUrl(string path) public async Task<string> GetFileUrlAsync(string path)
=> await GetDownloadUrl(path); => await GetDownloadUrlAsync(path);
public async Task<string> GetFolderUrl(string path) public async Task<string> GetFolderUrlAsync(string path)
=> await GetDownloadUrl(path); => await GetDownloadUrlAsync(path);
private async Task<string> GetDownloadUrl(string path) private async Task<string> GetDownloadUrlAsync(string path)
{ {
var response = await ApiClient.PostJson<DownloadUrlResponse>( var response = await ApiClient.PostJson<DownloadUrlResponse>(
$"{BaseApiUrl}/downloadUrl?path={path}" $"{BaseApiUrl}/downloadUrl?path={path}"

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MoonCore.Blazor.FlyonUi.Exceptions; using MoonCore.Blazor.FlyonUi.Exceptions;
using MoonCore.Blazor.FlyonUi.Toasts;
using MoonCore.Exceptions; using MoonCore.Exceptions;
namespace Moonlight.Client.Implementations; namespace Moonlight.Client.Implementations;
@@ -7,18 +8,25 @@ namespace Moonlight.Client.Implementations;
public class UnauthenticatedErrorFilter : IGlobalErrorFilter public class UnauthenticatedErrorFilter : IGlobalErrorFilter
{ {
private readonly NavigationManager Navigation; private readonly NavigationManager Navigation;
private readonly ToastService ToastService;
public UnauthenticatedErrorFilter(NavigationManager navigation) public UnauthenticatedErrorFilter(
NavigationManager navigation,
ToastService toastService
)
{ {
Navigation = navigation; Navigation = navigation;
ToastService = toastService;
} }
public Task<bool> HandleException(Exception ex) public async Task<bool> HandleExceptionAsync(Exception ex)
{ {
if (ex is not HttpApiException { Status: 401 }) if (ex is not HttpApiException { Status: 401 })
return Task.FromResult(false); return false;
await ToastService.InfoAsync("Session expired", "Your session has expired. Reloading..");
Navigation.NavigateTo("/api/auth/logout", true); Navigation.NavigateTo("/api/auth/logout", true);
return Task.FromResult(true); return true;
} }
} }

View File

@@ -22,11 +22,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Blazor-ApexCharts" Version="6.0.2" /> <PackageReference Include="Blazor-ApexCharts" Version="6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" />
<PackageReference Include="MoonCore" Version="1.9.9" /> <PackageReference Include="MoonCore" Version="2.0.0" />
<PackageReference Include="MoonCore.Blazor" Version="1.3.1" /> <PackageReference Include="MoonCore.Blazor.FlyonUi" Version="1.2.4" />
<PackageReference Include="MoonCore.Blazor.FlyonUi" Version="1.2.2" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" /> <PackageReference Include="System.Security.Claims" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,6 +4,6 @@ namespace Moonlight.Client.Plugins;
public interface IPluginStartup public interface IPluginStartup
{ {
public Task BuildApplication(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder); public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder);
public Task ConfigureApplication(IServiceProvider serviceProvider, WebAssemblyHost app); public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app);
} }

View File

@@ -9,9 +9,9 @@ public class WindowService
JsRuntime = jsRuntime; JsRuntime = jsRuntime;
} }
public async Task Open(string url, string title, int height, int width) public async Task OpenAsync(string url, string title, int height, int width)
=> await JsRuntime.InvokeVoidAsync("moonlight.window.open", url, title, height, width); => await JsRuntime.InvokeVoidAsync("moonlight.window.open", url, title, height, width);
public async Task Close() public async Task CloseAsync()
=> await JsRuntime.InvokeVoidAsync("moonlight.window.closeCurrent"); => await JsRuntime.InvokeVoidAsync("moonlight.window.closeCurrent");
} }

View File

@@ -9,7 +9,7 @@ namespace Moonlight.Client.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterAuthentication() private Task RegisterAuthenticationAsync()
{ {
WebAssemblyHostBuilder.Services.AddAuthorizationCore(); WebAssemblyHostBuilder.Services.AddAuthorizationCore();
WebAssemblyHostBuilder.Services.AddCascadingAuthenticationState(); WebAssemblyHostBuilder.Services.AddCascadingAuthenticationState();

View File

@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using MoonCore.Blazor.FlyonUi; using MoonCore.Blazor.FlyonUi;
using MoonCore.Blazor.Services;
using MoonCore.Extensions; using MoonCore.Extensions;
using MoonCore.Helpers; using MoonCore.Helpers;
using Moonlight.Client.Services; using Moonlight.Client.Services;
@@ -10,7 +9,7 @@ namespace Moonlight.Client.Startup;
public partial class Startup public partial class Startup
{ {
private Task RegisterBase() private Task RegisterBaseAsync()
{ {
WebAssemblyHostBuilder.RootComponents.Add<App>("#app"); WebAssemblyHostBuilder.RootComponents.Add<App>("#app");
WebAssemblyHostBuilder.RootComponents.Add<HeadOutlet>("head::after"); WebAssemblyHostBuilder.RootComponents.Add<HeadOutlet>("head::after");

View File

@@ -7,7 +7,7 @@ namespace Moonlight.Client.Startup;
public partial class Startup public partial class Startup
{ {
private Task SetupLogging() private Task SetupLoggingAsync()
{ {
var loggerFactory = new LoggerFactory(); var loggerFactory = new LoggerFactory();
@@ -18,7 +18,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task RegisterLogging() private Task RegisterLoggingAsync()
{ {
WebAssemblyHostBuilder.Logging.ClearProviders(); WebAssemblyHostBuilder.Logging.ClearProviders();
WebAssemblyHostBuilder.Logging.AddAnsiConsole(); WebAssemblyHostBuilder.Logging.AddAnsiConsole();

View File

@@ -6,7 +6,7 @@ namespace Moonlight.Client.Startup;
public partial class Startup public partial class Startup
{ {
private Task PrintVersion() private Task PrintVersionAsync()
{ {
// Fancy start console output... yes very fancy :> // Fancy start console output... yes very fancy :>
Console.Write("Running "); Console.Write("Running ");
@@ -27,7 +27,7 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task LoadConfiguration() private async Task LoadConfigurationAsync()
{ {
try try
{ {

View File

@@ -10,7 +10,7 @@ public partial class Startup
private IPluginStartup[] PluginStartups; private IPluginStartup[] PluginStartups;
private IServiceProvider PluginLoadServiceProvider; private IServiceProvider PluginLoadServiceProvider;
private Task InitializePlugins() private Task InitializePluginsAsync()
{ {
// Define minimal service collection // Define minimal service collection
var startupSc = new ServiceCollection(); var startupSc = new ServiceCollection();
@@ -38,13 +38,13 @@ public partial class Startup
return Task.CompletedTask; return Task.CompletedTask;
} }
private async Task HookPluginBuild() private async Task HookPluginBuildAsync()
{ {
foreach (var pluginAppStartup in PluginStartups) foreach (var pluginAppStartup in PluginStartups)
{ {
try try
{ {
await pluginAppStartup.BuildApplication(PluginLoadServiceProvider, WebAssemblyHostBuilder); await pluginAppStartup.BuildApplicationAsync(PluginLoadServiceProvider, WebAssemblyHostBuilder);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -57,13 +57,13 @@ public partial class Startup
} }
} }
private async Task HookPluginConfigure() private async Task HookPluginConfigureAsync()
{ {
foreach (var pluginAppStartup in PluginStartups) foreach (var pluginAppStartup in PluginStartups)
{ {
try try
{ {
await pluginAppStartup.ConfigureApplication(PluginLoadServiceProvider, WebAssemblyHost); await pluginAppStartup.ConfigureApplicationAsync(PluginLoadServiceProvider, WebAssemblyHost);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -16,33 +16,33 @@ public partial class Startup
public FrontendConfiguration Configuration { get; private set; } public FrontendConfiguration Configuration { get; private set; }
public Task Initialize(IPluginStartup[]? plugins = null) public Task InitializeAsync(IPluginStartup[]? plugins = null)
{ {
PluginStartups = plugins ?? []; PluginStartups = plugins ?? [];
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task AddMoonlight(WebAssemblyHostBuilder builder) public async Task AddMoonlightAsync(WebAssemblyHostBuilder builder)
{ {
WebAssemblyHostBuilder = builder; WebAssemblyHostBuilder = builder;
await PrintVersion(); await PrintVersionAsync();
await SetupLogging(); await SetupLoggingAsync();
await LoadConfiguration(); await LoadConfigurationAsync();
await InitializePlugins(); await InitializePluginsAsync();
await RegisterLogging(); await RegisterLoggingAsync();
await RegisterBase(); await RegisterBaseAsync();
await RegisterAuthentication(); await RegisterAuthenticationAsync();
await HookPluginBuild(); await HookPluginBuildAsync();
} }
public async Task AddMoonlight(WebAssemblyHost assemblyHost) public async Task AddMoonlightAsync(WebAssemblyHost assemblyHost)
{ {
WebAssemblyHost = assemblyHost; WebAssemblyHost = assemblyHost;
await HookPluginConfigure(); await HookPluginConfigureAsync();
} }
} }

View File

@@ -21,6 +21,8 @@
-ml-4 -ml-4
-translate-x-full -translate-x-full
-translate-y-1/2 -translate-y-1/2
[animation-duration:0.8s]
[animation-timing-function:ease]
absolute absolute
accordion accordion
accordion-bordered accordion-bordered
@@ -42,6 +44,7 @@ align-bottom
align-middle align-middle
animate-bounce animate-bounce
animate-ping animate-ping
animate-spin
aria-[current='page']:text-bg-soft-primary aria-[current='page']:text-bg-soft-primary
avatar avatar
avatar-placeholder avatar-placeholder
@@ -76,23 +79,31 @@ border
border-0 border-0
border-1 border-1
border-2 border-2
border-3
border-b border-b
border-b-2 border-b-2
border-b-base-content/20 border-b-base-content/20
border-b-primary
border-base-content border-base-content
border-base-content/20 border-base-content/20
border-base-content/25 border-base-content/25
border-base-content/40 border-base-content/40
border-base-content/5 border-base-content/5
border-dashed border-dashed
border-dotted
border-error/30 border-error/30
border-info/30 border-info/30
border-l-transparent
border-r-transparent
border-solid
border-success/30 border-success/30
border-t border-t
border-t-transparent
border-transparent border-transparent
border-warning/30 border-warning/30
bottom-0 bottom-0
bottom-full bottom-full
breadcrumbs
break-words break-words
btn btn
btn-accent btn-accent
@@ -160,6 +171,7 @@ duration-500
ease-in-out ease-in-out
ease-linear ease-linear
end-3 end-3
error-message
file-upload-complete:progress-success file-upload-complete:progress-success
fill-base-content fill-base-content
fill-black fill-black
@@ -187,6 +199,8 @@ font-inter
font-medium font-medium
font-normal font-normal
font-semibold font-semibold
footer
footer-center
gap-0.5 gap-0.5
gap-1 gap-1
gap-1.5 gap-1.5
@@ -220,10 +234,13 @@ helper-text
hidden hidden
hover:bg-primary/5 hover:bg-primary/5
hover:bg-transparent hover:bg-transparent
hover:cursor-pointer
hover:text-base-content hover:text-base-content
hover:text-base-content/60 hover:text-base-content/60
hover:text-primary hover:text-primary
image-full image-full
indicator
indicator-item
inline inline
inline-block inline-block
inline-flex inline-flex
@@ -281,7 +298,6 @@ list-disc
list-inside list-inside
list-none list-none
loading loading
loading-lg
loading-sm loading-sm
loading-spinner loading-spinner
loading-xl loading-xl
@@ -296,6 +312,7 @@ max-md:flex-wrap
max-md:justify-center max-md:justify-center
max-sm:hidden max-sm:hidden
max-w-7xl max-w-7xl
max-w-8
max-w-80 max-w-80
max-w-full max-w-full
max-w-lg max-w-lg
@@ -360,10 +377,12 @@ mt-8
mx-1 mx-1
mx-auto mx-auto
my-3 my-3
my-5
my-auto my-auto
object-cover object-cover
opacity-0 opacity-0
opacity-100 opacity-100
opacity-75
open open
origin-top-left origin-top-left
outline outline
@@ -396,7 +415,6 @@ pt-0
pt-0.5 pt-0.5
pt-2 pt-2
pt-3 pt-3
px-0.5
px-1.5 px-1.5
px-2 px-2
px-2.5 px-2.5
@@ -471,10 +489,12 @@ space-x-2.5
space-y-1 space-y-1
space-y-4 space-y-4
sr-only sr-only
stack
static static
status status
status-error status-error
sticky sticky
success-message
switch switch
tab tab
tab-active tab-active

View File

@@ -1,7 +1,7 @@
<label for="@Id" class="btn btn-square border-0 ring-0 outline-0" style="background-color: @Value"> <label for="@Id" class="btn btn-square border-0 ring-0 outline-0" style="background-color: @Value">
<i class="text-lg text-base-content @Icon"></i> <i class="text-lg text-base-content @Icon"></i>
</label> </label>
<input value="@Value" @oninput="Update" id="@Id" type="color" class="h-0 w-0 opacity-0"/> <input value="@Value" @oninput="UpdateAsync" id="@Id" type="color" class="h-0 w-0 opacity-0"/>
@code @code
{ {
@@ -37,7 +37,7 @@
Id = $"color-selector-{GetHashCode()}"; Id = $"color-selector-{GetHashCode()}";
} }
private async Task Update(ChangeEventArgs args) private async Task UpdateAsync(ChangeEventArgs args)
{ {
Value = args.Value?.ToString() ?? "#FFFFFF"; Value = args.Value?.ToString() ?? "#FFFFFF";
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);

View File

@@ -17,7 +17,7 @@
for all SignalR Hubs to be synced. for all SignalR Hubs to be synced.
</p> </p>
<div class="mt-5"> <div class="mt-5">
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<WButton OnClick="OnClick" CssClasses="btn btn-primary"> <WButton OnClick="OnClick" CssClasses="btn btn-primary">
Send broadcast Send broadcast
</WButton> </WButton>
@@ -30,9 +30,9 @@
{ {
private HubConnection? Connection; private HubConnection? Connection;
private async Task Load(LazyLoader lazyLoader) private async Task LoadAsync(LazyLoader lazyLoader)
{ {
await lazyLoader.UpdateText("Connecting to SignalR endpoint"); await lazyLoader.UpdateTextAsync("Connecting to SignalR endpoint");
Connection = new HubConnectionBuilder() Connection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/api/admin/system/diagnose/ws")) .WithUrl(Navigation.ToAbsoluteUri("/api/admin/system/diagnose/ws"))
@@ -41,7 +41,7 @@
Connection.On( Connection.On(
"Pong", "Pong",
async () => await ToastService.Success("Received broadcast") async () => await ToastService.SuccessAsync("Received broadcast")
); );
await Connection.StartAsync(); await Connection.StartAsync();

View File

@@ -137,7 +137,7 @@
} }
else else
{ {
<input @onclick="_ => UpdateRadiusBox(possibleValue)" type="radio" name="radius-box" class="radio hidden"/> <input @onclick="_ => UpdateRadiusBoxAsync(possibleValue)" type="radio" name="radius-box" class="radio hidden"/>
} }
<span class="label-text w-full"> <span class="label-text w-full">
<div class="pe-1.5 pt-1.5" aria-hidden="true"> <div class="pe-1.5 pt-1.5" aria-hidden="true">
@@ -164,7 +164,7 @@
} }
else else
{ {
<input @onclick="_ => UpdateRadiusField(possibleValue)" type="radio" name="radius-field" class="radio hidden"/> <input @onclick="_ => UpdateRadiusFieldAsync(possibleValue)" type="radio" name="radius-field" class="radio hidden"/>
} }
<span class="label-text w-full"> <span class="label-text w-full">
<div class="pe-1.5 pt-1.5" aria-hidden="true"> <div class="pe-1.5 pt-1.5" aria-hidden="true">
@@ -191,7 +191,7 @@
} }
else else
{ {
<input @onclick="_ => UpdateRadiusSelector(possibleValue)" type="radio" name="radius-selector" class="radio hidden"/> <input @onclick="_ => UpdateRadiusSelectorAsync(possibleValue)" type="radio" name="radius-selector" class="radio hidden"/>
} }
<span class="label-text w-full"> <span class="label-text w-full">
<div class="pe-1.5 pt-1.5" aria-hidden="true"> <div class="pe-1.5 pt-1.5" aria-hidden="true">
@@ -302,19 +302,19 @@
set => Theme.Noise = value ? 1 : 0; set => Theme.Noise = value ? 1 : 0;
} }
private async Task UpdateRadiusBox(float value) private async Task UpdateRadiusBoxAsync(float value)
{ {
Theme.RadiusBox = value; Theme.RadiusBox = value;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
private async Task UpdateRadiusField(float value) private async Task UpdateRadiusFieldAsync(float value)
{ {
Theme.RadiusField = value; Theme.RadiusField = value;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
private async Task UpdateRadiusSelector(float value) private async Task UpdateRadiusSelectorAsync(float value)
{ {
Theme.RadiusSelector = value; Theme.RadiusSelector = value;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);

View File

@@ -42,7 +42,7 @@
public event Func<Task> OnStateChanged; public event Func<Task> OnStateChanged;
public bool ShowMobileNavigation { get; private set; } = false; public bool ShowMobileNavigation { get; private set; } = false;
public async Task ToggleMobileNavigation() public async Task ToggleMobileNavigationAsync()
{ {
ShowMobileNavigation = !ShowMobileNavigation; ShowMobileNavigation = !ShowMobileNavigation;
await OnStateChanged(); await OnStateChanged();

View File

@@ -5,7 +5,7 @@
<header class="flex items-center px-4 lg:hidden border-b border-base-content/5"> <header class="flex items-center px-4 lg:hidden border-b border-base-content/5">
<div class="py-2.5"> <div class="py-2.5">
<span class="relative"> <span class="relative">
<button @onclick="Layout.ToggleMobileNavigation" aria-label="Open navigation" <button @onclick="Layout.ToggleMobileNavigationAsync" aria-label="Open navigation"
class="relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 sm:text-sm/5 text-base-content" class="relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 sm:text-sm/5 text-base-content"
type="button"> type="button">
<i class="icon-menu text-xl"></i> <i class="icon-menu text-xl"></i>

View File

@@ -95,7 +95,7 @@
</div> </div>
</div> </div>
</div> </div>
<a href="#" @onclick:preventDefault @onclick="Logout" class="flex items-center"> <a href="#" @onclick:preventDefault @onclick="LogoutAsync" class="flex items-center">
<i class="icon-log-out text-lg"></i> <i class="icon-log-out text-lg"></i>
</a> </a>
</div> </div>
@@ -121,7 +121,7 @@
<div class="truncate">Moonlight v2.1</div> <div class="truncate">Moonlight v2.1</div>
</div> </div>
<button @onclick="Layout.ToggleMobileNavigation" aria-label="Close navigation" type="button" <button @onclick="Layout.ToggleMobileNavigationAsync" aria-label="Close navigation" type="button"
class="relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 text-base-content"> class="relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 text-base-content">
<i class="icon-x text-lg"></i> <i class="icon-x text-lg"></i>
</button> </button>
@@ -180,7 +180,7 @@
<div class="flex flex-col gap-0.5"> <div class="flex flex-col gap-0.5">
<div class="relative"> <div class="relative">
<a class="flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-base/6 sm:py-2 sm:text-sm/5 text-base-content" <a class="flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-base/6 sm:py-2 sm:text-sm/5 text-base-content"
href="#" @onclick:preventDefault @onclick="Logout"> href="#" @onclick:preventDefault @onclick="LogoutAsync">
<i class="icon-log-out"></i> <i class="icon-log-out"></i>
<span class="truncate">Logout</span> <span class="truncate">Logout</span>
</a> </a>
@@ -252,13 +252,13 @@
if (!Layout.ShowMobileNavigation) if (!Layout.ShowMobileNavigation)
return; return;
await Layout.ToggleMobileNavigation(); await Layout.ToggleMobileNavigationAsync();
}; };
return Task.CompletedTask; return Task.CompletedTask;
} }
private Task Logout() private Task LogoutAsync()
{ {
Navigation.NavigateTo("/api/auth/logout", true); Navigation.NavigateTo("/api/auth/logout", true);
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -7,7 +7,7 @@
<div class="flex h-screen justify-center items-center"> <div class="flex h-screen justify-center items-center">
<div class="sm:min-w-md"> <div class="sm:min-w-md">
<div class="bg-base-100 shadow-base-300/20 z-1 w-full space-y-6 rounded-xl p-6 shadow-md lg:p-8"> <div class="bg-base-100 shadow-base-300/20 z-1 w-full space-y-6 rounded-xl p-6 shadow-md lg:p-8">
<LazyLoader EnableDefaultSpacing="false" Load="Load"> <LazyLoader EnableDefaultSpacing="false" Load="LoadAsync">
@if (ShowSelection) @if (ShowSelection)
{ {
<div class="flex justify-center items-center gap-3"> <div class="flex justify-center items-center gap-3">
@@ -34,7 +34,7 @@
if (config == null) // Ignore all schemes which have no ui configured if (config == null) // Ignore all schemes which have no ui configured
continue; continue;
<button @onclick="() => Start(scheme)" class="btn btn-text w-full" <button @onclick="() => StartAsync(scheme)" class="btn btn-text w-full"
style="background-color: @(config.Color)"> style="background-color: @(config.Color)">
<img src="@config.IconUrl" <img src="@config.IconUrl"
alt="scheme icon" alt="scheme icon"
@@ -71,7 +71,7 @@
}; };
} }
private async Task Load(LazyLoader arg) private async Task LoadAsync(LazyLoader arg)
{ {
AuthSchemes = await ApiClient.GetJson<AuthSchemeResponse[]>( AuthSchemes = await ApiClient.GetJson<AuthSchemeResponse[]>(
"api/auth" "api/auth"
@@ -82,12 +82,12 @@
// showing the selection screen // showing the selection screen
if (AuthSchemes.Length == 1) if (AuthSchemes.Length == 1)
await Start(AuthSchemes[0]); await StartAsync(AuthSchemes[0]);
else else
ShowSelection = true; ShowSelection = true;
} }
private Task Start(AuthSchemeResponse scheme) private Task StartAsync(AuthSchemeResponse scheme)
{ {
Navigation.NavigateTo($"/api/auth/{scheme.Identifier}", true); Navigation.NavigateTo($"/api/auth/{scheme.Identifier}", true);
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -16,7 +16,7 @@
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Create Create
</WButton> </WButton>
@@ -66,17 +66,17 @@
var response = await ApiClient.PostJson<CreateApiKeyResponse>("api/admin/apikeys", Request); var response = await ApiClient.PostJson<CreateApiKeyResponse>("api/admin/apikeys", Request);
await DownloadService.Download( await DownloadService.DownloadAsync(
$"moonlight-key-{response.Id}.txt", $"moonlight-key-{response.Id}.txt",
response.Secret response.Secret
); );
await AlertService.Success( await AlertService.SuccessAsync(
"API Key successfully created", "API Key successfully created",
"The API Key has been downloaded. Dont lose it, you cant view it anymore" "The API Key has been downloaded. Dont lose it, you cant view it anymore"
); );
await ToastService.Success("Successfully created api key"); await ToastService.SuccessAsync("Successfully created api key");
Navigation.NavigateTo("/admin/api"); Navigation.NavigateTo("/admin/api");
} }
} }

View File

@@ -51,7 +51,7 @@
<DataGrid @ref="Grid" <DataGrid @ref="Grid"
TGridItem="ApiKeyResponse" TGridItem="ApiKeyResponse"
ItemsProvider="ItemsProvider" ItemsProvider="ItemsProviderAsync"
EnableFiltering="true" EnableFiltering="true"
EnablePagination="true"> EnablePagination="true">
<PropertyColumn Field="x => x.Id" Sortable="true" /> <PropertyColumn Field="x => x.Id" Sortable="true" />
@@ -92,7 +92,7 @@
{ {
private DataGrid<ApiKeyResponse> Grid; private DataGrid<ApiKeyResponse> Grid;
private async Task<DataGridItemResult<ApiKeyResponse>> ItemsProvider(DataGridItemRequest request) private async Task<DataGridItemResult<ApiKeyResponse>> ItemsProviderAsync(DataGridItemRequest request)
{ {
var query = $"?startIndex={request.StartIndex}&count={request.Count}"; var query = $"?startIndex={request.StartIndex}&count={request.Count}";
@@ -116,13 +116,13 @@
private async Task DeleteAsync(ApiKeyResponse apiKeyResponse) private async Task DeleteAsync(ApiKeyResponse apiKeyResponse)
{ {
await AlertService.ConfirmDanger( await AlertService.ConfirmDangerAsync(
"API Key deletion", "API Key Deletion",
$"Do you really want to delete the api key '{apiKeyResponse.Description}'", $"Do you really want to delete the api key '{apiKeyResponse.Description}'",
async () => async () =>
{ {
await ApiClient.Delete($"api/admin/apikeys/{apiKeyResponse.Id}"); await ApiClient.Delete($"api/admin/apikeys/{apiKeyResponse.Id}");
await ToastService.Success("Successfully deleted api key"); await ToastService.SuccessAsync("Successfully deleted api key");
await Grid.RefreshAsync(); await Grid.RefreshAsync();
} }

View File

@@ -7,13 +7,13 @@
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject ToastService ToastService @inject ToastService ToastService
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<PageHeader Title="Update API Key"> <PageHeader Title="Update API Key">
<a href="/admin/api" class="btn btn-secondary"> <a href="/admin/api" class="btn btn-secondary">
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Update Update
</WButton> </WButton>
@@ -40,7 +40,7 @@
private HandleForm Form; private HandleForm Form;
private UpdateApiKeyRequest Request; private UpdateApiKeyRequest Request;
private async Task Load(LazyLoader _) private async Task LoadAsync(LazyLoader _)
{ {
var detail = await ApiClient.GetJson<ApiKeyResponse>($"api/admin/apikeys/{Id}"); var detail = await ApiClient.GetJson<ApiKeyResponse>($"api/admin/apikeys/{Id}");
@@ -54,7 +54,7 @@
{ {
await ApiClient.Patch($"api/admin/apikeys/{Id}", Request); await ApiClient.Patch($"api/admin/apikeys/{Id}", Request);
await ToastService.Success("Successfully updated api key"); await ToastService.SuccessAsync("Successfully updated api key");
Navigation.NavigateTo("/admin/api"); Navigation.NavigateTo("/admin/api");
} }
} }

View File

@@ -26,17 +26,17 @@
includes your installed theme and plugins. For more information, have a look at <a class="text-primary" href="https://help.moonlightpanel.xyz">our docs</a> includes your installed theme and plugins. For more information, have a look at <a class="text-primary" href="https://help.moonlightpanel.xyz">our docs</a>
</p> </p>
<WButton OnClick="GenerateFrontend" CssClasses="btn btn-primary mt-5">Generate frontend.zip</WButton> <WButton OnClick="GenerateFrontendAsync" CssClasses="btn btn-primary mt-5">Generate frontend.zip</WButton>
</div> </div>
</div> </div>
</div> </div>
@code @code
{ {
private async Task GenerateFrontend(WButton _) private async Task GenerateFrontendAsync(WButton _)
{ {
var stream = await ApiClient.GetStream("api/admin/system/advanced/frontend"); var stream = await ApiClient.GetStream("api/admin/system/advanced/frontend");
await DownloadService.Download("frontend.zip", stream); await DownloadService.DownloadAsync("frontend.zip", stream);
} }
} }

View File

@@ -30,7 +30,7 @@
<div class="my-8"> <div class="my-8">
<DataGrid TGridItem="ThemeResponse" <DataGrid TGridItem="ThemeResponse"
ItemsProvider="ItemsProvider" ItemsProvider="ItemsProviderAsync"
EnableFiltering="true" EnableFiltering="true"
EnablePagination="true"> EnablePagination="true">
@@ -105,7 +105,7 @@
{ {
private DataGrid<ThemeResponse> Grid; private DataGrid<ThemeResponse> Grid;
private async Task<DataGridItemResult<ThemeResponse>> ItemsProvider(DataGridItemRequest request) private async Task<DataGridItemResult<ThemeResponse>> ItemsProviderAsync(DataGridItemRequest request)
{ {
var query = $"?startIndex={request.StartIndex}&count={request.Count}"; var query = $"?startIndex={request.StartIndex}&count={request.Count}";
@@ -142,13 +142,13 @@
{ {
if (!file.Name.EndsWith(".json")) if (!file.Name.EndsWith(".json"))
{ {
await ToastService.Error($"Unable to import {file.Name}", "Only .json files are supported"); await ToastService.ErrorAsync($"Unable to import {file.Name}", "Only .json files are supported");
continue; continue;
} }
if (file.Size > maxFileSize) if (file.Size > maxFileSize)
{ {
await ToastService.Error($"Unable to import {file.Name}", "Exceeded the maximum file limit of 1MB"); await ToastService.ErrorAsync($"Unable to import {file.Name}", "Exceeded the maximum file limit of 1MB");
continue; continue;
} }
@@ -159,7 +159,7 @@
if (themeTransfer == null) if (themeTransfer == null)
{ {
await ToastService.Error($"Unable to import {file.Name}", "Failed to deserialize the content"); await ToastService.ErrorAsync($"Unable to import {file.Name}", "Failed to deserialize the content");
continue; continue;
} }
@@ -173,7 +173,7 @@
Version = themeTransfer.Version Version = themeTransfer.Version
}); });
await ToastService.Success("Successfully imported theme", theme.Name); await ToastService.SuccessAsync("Successfully imported theme", theme.Name);
await Grid.RefreshAsync(); await Grid.RefreshAsync();
} }
@@ -203,19 +203,19 @@
var fileName = $"{transfer.Name.Replace(" ", string.Empty).Trim()}.json"; var fileName = $"{transfer.Name.Replace(" ", string.Empty).Trim()}.json";
await DownloadService.Download(fileName, json); await DownloadService.DownloadAsync(fileName, json);
} }
private async Task DeleteAsync(ThemeResponse response) private async Task DeleteAsync(ThemeResponse response)
{ {
await AlertService.ConfirmDanger( await AlertService.ConfirmDangerAsync(
"Theme deletion", "Theme deletion",
$"Do you really want to delete the theme: {response.Name}", $"Do you really want to delete the theme: {response.Name}",
async () => async () =>
{ {
await ThemeService.DeleteAsync(response.Id); await ThemeService.DeleteAsync(response.Id);
await ToastService.Success("Successfully deleted theme"); await ToastService.SuccessAsync("Successfully deleted theme");
await Grid.RefreshAsync(); await Grid.RefreshAsync();
} }
); );

View File

@@ -14,7 +14,7 @@
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Create Create
</WButton> </WButton>
@@ -59,7 +59,7 @@
private async Task OnValidSubmit() private async Task OnValidSubmit()
{ {
await ThemeService.CreateAsync(Request); await ThemeService.CreateAsync(Request);
await ToastService.Success("Successfully created theme"); await ToastService.SuccessAsync("Successfully created theme");
NavigationManager.NavigateTo("/admin/system/customisation"); NavigationManager.NavigateTo("/admin/system/customisation");
} }

View File

@@ -9,13 +9,13 @@
@inject ToastService ToastService @inject ToastService ToastService
@inject NavigationManager Navigation @inject NavigationManager Navigation
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<PageHeader Title="@($"Update {Request.Name}")"> <PageHeader Title="@($"Update {Request.Name}")">
<a href="/admin/system/customisation" class="btn btn-secondary"> <a href="/admin/system/customisation" class="btn btn-secondary">
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Update Update
</WButton> </WButton>
@@ -80,7 +80,7 @@
private HandleForm Form; private HandleForm Form;
private async Task Load(LazyLoader _) private async Task LoadAsync(LazyLoader _)
{ {
Response = await ThemeService.GetAsync(Id); Response = await ThemeService.GetAsync(Id);
@@ -100,7 +100,7 @@
{ {
await ThemeService.UpdateAsync(Id, Request); await ThemeService.UpdateAsync(Id, Request);
await ToastService.Success("Successfully updated theme"); await ToastService.SuccessAsync("Successfully updated theme");
Navigation.NavigateTo("/admin/system/customisation"); Navigation.NavigateTo("/admin/system/customisation");
} }
} }

View File

@@ -28,11 +28,11 @@
If you only want to export specific parts of the diagnose report, click on "Advanced" and select the desired providers If you only want to export specific parts of the diagnose report, click on "Advanced" and select the desired providers
</p> </p>
<WButton OnClick="GenerateDiagnose" CssClasses="btn btn-primary my-5">Generate report</WButton> <WButton OnClick="GenerateDiagnoseAsync" CssClasses="btn btn-primary my-5">Generate report</WButton>
<div class="text-sm"> <div class="text-sm">
<a class="text-primary cursor-pointer flex items-center" @onclick:preventDefault <a class="text-primary cursor-pointer flex items-center" @onclick:preventDefault
@onclick="ToggleDropDown"> @onclick="ToggleDropDownAsync">
<span class="me-1.5">Advanced</span> <span class="me-1.5">Advanced</span>
@if (DropdownOpen) @if (DropdownOpen)
{ {
@@ -45,7 +45,7 @@
</a> </a>
<div class="@(DropdownOpen ? "" : "hidden")"> <div class="@(DropdownOpen ? "" : "hidden")">
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<div class="mb-2 py-2 border-b border-base-content/70 flex items-center gap-3"> <div class="mb-2 py-2 border-b border-base-content/70 flex items-center gap-3">
<input id="selectall_checkbox" @bind="SelectAll" type="checkbox" class="checkbox checkbox-primary checkbox-xs"> <input id="selectall_checkbox" @bind="SelectAll" type="checkbox" class="checkbox checkbox-primary checkbox-xs">
<label for="selectall_checkbox">Select all</label> <label for="selectall_checkbox">Select all</label>
@@ -86,7 +86,7 @@
} }
} }
private async Task Load(LazyLoader arg) private async Task LoadAsync(LazyLoader arg)
{ {
var providers = await ApiClient.GetJson<DiagnoseProvideResponse[]>( var providers = await ApiClient.GetJson<DiagnoseProvideResponse[]>(
"api/admin/system/diagnose/providers" "api/admin/system/diagnose/providers"
@@ -96,7 +96,7 @@
.ToDictionary(x => x, _ => true); .ToDictionary(x => x, _ => true);
} }
private async Task GenerateDiagnose(WButton button) private async Task GenerateDiagnoseAsync(WButton button)
{ {
var request = new GenerateDiagnoseRequest(); var request = new GenerateDiagnoseRequest();
@@ -111,11 +111,11 @@
var stream = await ApiClient.PostStream("api/admin/system/diagnose", request); var stream = await ApiClient.PostStream("api/admin/system/diagnose", request);
await DownloadService.Download("diagnose.zip", stream); await DownloadService.DownloadAsync("diagnose.zip", stream);
} }
private async Task ToggleDropDown() private async Task ToggleDropDownAsync()
{ {
DropdownOpen = !DropdownOpen; DropdownOpen = !DropdownOpen;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);

View File

@@ -19,7 +19,7 @@
</HelperMessage> </HelperMessage>
</div> </div>
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-5"> <div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-5">
<StatCard Title="Servers" Text="@Stats.Servers.ToString()" Icon="icon-server"/> <StatCard Title="Servers" Text="@Stats.Servers.ToString()" Icon="icon-server"/>
<StatCard Title="Recurring" Text="@Stats.Recurring.ToString()" Icon="icon-calendar-sync"/> <StatCard Title="Recurring" Text="@Stats.Recurring.ToString()" Icon="icon-calendar-sync"/>
@@ -39,7 +39,7 @@
{ {
private HangfireStatsResponse Stats; private HangfireStatsResponse Stats;
private async Task Load(LazyLoader _) private async Task LoadAsync(LazyLoader _)
{ {
Stats = await ApiClient.GetJson<HangfireStatsResponse>( Stats = await ApiClient.GetJson<HangfireStatsResponse>(
"api/admin/system/hangfire/stats" "api/admin/system/hangfire/stats"

View File

@@ -13,7 +13,7 @@
<NavTabs Index="0" Names="UiConstants.AdminNavNames" Links="UiConstants.AdminNavLinks" /> <NavTabs Index="0" Names="UiConstants.AdminNavNames" Links="UiConstants.AdminNavLinks" />
</div> </div>
<LazyLoader Load="LoadOverview"> <LazyLoader Load="LoadOverviewAsync">
<div class="gap-5 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4"> <div class="gap-5 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4">
<StatCard Title="CPU Usage" Text="@(OverviewData.CpuUsage + "%")" Icon="icon-cpu"/> <StatCard Title="CPU Usage" Text="@(OverviewData.CpuUsage + "%")" Icon="icon-cpu"/>
<StatCard Title="Memory Usage" Text="@(Formatter.FormatSize(OverviewData.MemoryUsage))" Icon="icon-memory-stick"/> <StatCard Title="Memory Usage" Text="@(Formatter.FormatSize(OverviewData.MemoryUsage))" Icon="icon-memory-stick"/>
@@ -28,7 +28,7 @@
<div class="flex"> <div class="flex">
<div class="card card-body"> <div class="card card-body">
<div class="flex justify-center"> <div class="flex justify-center">
<WButton OnClick="Restart" CssClasses="btn btn-error w-full"> <WButton OnClick="RestartAsync" CssClasses="btn btn-error w-full">
<i class="icon-repeat me-2"></i> <i class="icon-repeat me-2"></i>
Restart/Shutdown Restart/Shutdown
</WButton> </WButton>
@@ -41,12 +41,12 @@
{ {
private SystemOverviewResponse OverviewData; private SystemOverviewResponse OverviewData;
private async Task LoadOverview(LazyLoader arg) private async Task LoadOverviewAsync(LazyLoader arg)
{ {
OverviewData = await ApiClient.GetJson<SystemOverviewResponse>("api/admin/system"); OverviewData = await ApiClient.GetJson<SystemOverviewResponse>("api/admin/system");
} }
private async Task Restart(WButton _) private async Task RestartAsync(WButton _)
{ {
await ApiClient.Post("api/admin/system/shutdown"); await ApiClient.Post("api/admin/system/shutdown");
} }

View File

@@ -12,7 +12,7 @@
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Create Create
</WButton> </WButton>
@@ -67,7 +67,7 @@
await ApiClient.Post("api/admin/users", Request); await ApiClient.Post("api/admin/users", Request);
await ToastService.Success("Successfully created user"); await ToastService.SuccessAsync("Successfully created user");
Navigation.NavigateTo("/admin/users"); Navigation.NavigateTo("/admin/users");
} }
} }

View File

@@ -20,7 +20,7 @@
<DataGrid @ref="Grid" <DataGrid @ref="Grid"
TGridItem="UserResponse" TGridItem="UserResponse"
ItemsProvider="ItemsProvider" ItemsProvider="ItemsProviderAsync"
EnableFiltering="true" EnableFiltering="true"
EnablePagination="true"> EnablePagination="true">
<PropertyColumn Field="x => x.Id" Sortable="true" /> <PropertyColumn Field="x => x.Id" Sortable="true" />
@@ -46,7 +46,7 @@
{ {
private DataGrid<UserResponse> Grid; private DataGrid<UserResponse> Grid;
private async Task<DataGridItemResult<UserResponse>> ItemsProvider(DataGridItemRequest request) private async Task<DataGridItemResult<UserResponse>> ItemsProviderAsync(DataGridItemRequest request)
{ {
var query = $"?startIndex={request.StartIndex}&count={request.Count}"; var query = $"?startIndex={request.StartIndex}&count={request.Count}";
@@ -70,13 +70,13 @@
private async Task DeleteAsync(UserResponse response) private async Task DeleteAsync(UserResponse response)
{ {
await AlertService.ConfirmDanger( await AlertService.ConfirmDangerAsync(
"User deletion", "User deletion",
$"Do you really want to delete the user '{response.Username}'", $"Do you really want to delete the user '{response.Username}'",
async () => async () =>
{ {
await ApiClient.Delete($"api/admin/users/{response.Id}"); await ApiClient.Delete($"api/admin/users/{response.Id}");
await ToastService.Success("Successfully deleted user"); await ToastService.SuccessAsync("Successfully deleted user");
await Grid.RefreshAsync(); await Grid.RefreshAsync();
} }

View File

@@ -8,13 +8,13 @@
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject ToastService ToastService @inject ToastService ToastService
<LazyLoader Load="Load"> <LazyLoader Load="LoadAsync">
<PageHeader Title="Update User"> <PageHeader Title="Update User">
<a href="/admin/users" class="btn btn-secondary"> <a href="/admin/users" class="btn btn-secondary">
<i class="icon-chevron-left"></i> <i class="icon-chevron-left"></i>
Back Back
</a> </a>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary"> <WButton OnClick="Form.SubmitAsync" CssClasses="btn btn-primary">
<i class="icon-check"></i> <i class="icon-check"></i>
Update Update
</WButton> </WButton>
@@ -62,7 +62,7 @@
private List<string> Permissions = []; private List<string> Permissions = [];
private async Task Load(LazyLoader _) private async Task LoadAsync(LazyLoader _)
{ {
var detail = await ApiClient.GetJson<UserResponse>($"api/admin/users/{Id}"); var detail = await ApiClient.GetJson<UserResponse>($"api/admin/users/{Id}");
@@ -82,7 +82,7 @@
await ApiClient.Patch($"api/admin/users/{Id}", Request); await ApiClient.Patch($"api/admin/users/{Id}", Request);
await ToastService.Success("Successfully updated user"); await ToastService.SuccessAsync("Successfully updated user");
Navigation.NavigateTo("/admin/users"); Navigation.NavigateTo("/admin/users");
} }
} }