Added audit logging. Added admin view for audit log
This commit is contained in:
@@ -9,4 +9,5 @@ public class AuditLogEntry
|
|||||||
public string JsonData { get; set; } = "";
|
public string JsonData { get; set; } = "";
|
||||||
public bool System { get; set; }
|
public bool System { get; set; }
|
||||||
public string Ip { get; set; } = "";
|
public string Ip { get; set; } = "";
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -8,4 +8,5 @@ public class ErrorLogEntry
|
|||||||
public string JsonData { get; set; } = "";
|
public string JsonData { get; set; } = "";
|
||||||
public string Ip { get; set; } = "";
|
public string Ip { get; set; } = "";
|
||||||
public string Class { get; set; } = "";
|
public string Class { get; set; } = "";
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -9,4 +9,5 @@ public class SecurityLogEntry
|
|||||||
public string Ip { get; set; } = "";
|
public string Ip { get; set; } = "";
|
||||||
public SecurityLogType Type { get; set; }
|
public SecurityLogType Type { get; set; }
|
||||||
public string JsonData { get; set; } = "";
|
public string JsonData { get; set; } = "";
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
925
Moonlight/App/Database/Migrations/20230305014834_AddedLoggingAndDbStuff.Designer.cs
generated
Normal file
925
Moonlight/App/Database/Migrations/20230305014834_AddedLoggingAndDbStuff.Designer.cs
generated
Normal file
@@ -0,0 +1,925 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Moonlight.App.Database;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DataContext))]
|
||||||
|
[Migration("20230305014834_AddedLoggingAndDbStuff")]
|
||||||
|
partial class AddedLoggingAndDbStuff
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("AaPanelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Databases");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Default")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("DockerImages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SharedDomainId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.HasIndex("SharedDomainId");
|
||||||
|
|
||||||
|
b.ToTable("Domains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConfigFiles")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallDockerImage")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallEntrypoint")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallScript")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Startup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StartupDetection")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StopCommand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Images");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageTags");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("DefaultValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LoadingMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AuditLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Class")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Stacktrace")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ErrorLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SecurityLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Fqdn")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("HttpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MoonlightDaemonPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("SftpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ssl")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Token")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TokenId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Nodes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Port")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("NodeAllocations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Action")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationClientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NotificationClientId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationActions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Identifier")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Revokes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Disk")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("DockerImageIndex")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Installing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("MainAllocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Memory")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("OverrideStartup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Suspended")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.HasIndex("MainAllocationId");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Servers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Bytes")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Created")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerBackups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SharedDomain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("CloudflareId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SharedDomains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Duration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("SellPassId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Amount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Disk")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Memory")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.HasIndex("SubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("SubscriptionLimits");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Answer")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsQuestion")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSupport")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSystem")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("RecipientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SenderId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RecipientId");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.ToTable("SupportMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("Admin")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("DiscordDiscriminator")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("DiscordId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("DiscordUsername")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SubscriptionDuration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("SubscriptionSince")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("SupportPending")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TokenValidTime")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("TotpEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("TotpSecret")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("DockerImages")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SharedDomainId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
|
||||||
|
b.Navigation("SharedDomain");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("Tags")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("NodeId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NotificationClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("NotificationClient");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MainAllocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NodeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
|
||||||
|
b.Navigation("MainAllocation");
|
||||||
|
|
||||||
|
b.Navigation("Node");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Backups")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", null)
|
||||||
|
.WithMany("Limits")
|
||||||
|
.HasForeignKey("SubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Recipient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RecipientId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Sender")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SenderId");
|
||||||
|
|
||||||
|
b.Navigation("Recipient");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", "Subscription")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("Subscription");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("DockerImages");
|
||||||
|
|
||||||
|
b.Navigation("Tags");
|
||||||
|
|
||||||
|
b.Navigation("Variables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Allocations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Allocations");
|
||||||
|
|
||||||
|
b.Navigation("Backups");
|
||||||
|
|
||||||
|
b.Navigation("Variables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Limits");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedLoggingAndDbStuff : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ErrorLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Stacktrace = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
System = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
JsonData = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Class = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ErrorLog", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SecurityLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
System = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Type = table.Column<int>(type: "int", nullable: false),
|
||||||
|
JsonData = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SecurityLog", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ErrorLog");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SecurityLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
934
Moonlight/App/Database/Migrations/20230305021844_AddedDatesToLogs.Designer.cs
generated
Normal file
934
Moonlight/App/Database/Migrations/20230305021844_AddedDatesToLogs.Designer.cs
generated
Normal file
@@ -0,0 +1,934 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Moonlight.App.Database;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DataContext))]
|
||||||
|
[Migration("20230305021844_AddedDatesToLogs")]
|
||||||
|
partial class AddedDatesToLogs
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("AaPanelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Databases");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Default")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("DockerImages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SharedDomainId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.HasIndex("SharedDomainId");
|
||||||
|
|
||||||
|
b.ToTable("Domains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConfigFiles")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallDockerImage")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallEntrypoint")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallScript")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Startup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StartupDetection")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StopCommand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Images");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageTags");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("DefaultValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LoadingMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AuditLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Class")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Stacktrace")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ErrorLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SecurityLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Fqdn")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("HttpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MoonlightDaemonPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("SftpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ssl")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Token")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TokenId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Nodes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Port")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("NodeAllocations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Action")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationClientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NotificationClientId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationActions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Identifier")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Revokes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Disk")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("DockerImageIndex")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Installing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("MainAllocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Memory")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("OverrideStartup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Suspended")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.HasIndex("MainAllocationId");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.ToTable("Servers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Bytes")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Created")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerBackups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SharedDomain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("CloudflareId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SharedDomains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Duration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("SellPassId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Amount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Disk")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Memory")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.HasIndex("SubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("SubscriptionLimits");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Answer")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsQuestion")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSupport")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSystem")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("RecipientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SenderId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RecipientId");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.ToTable("SupportMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("Admin")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("DiscordDiscriminator")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<long>("DiscordId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("DiscordUsername")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SubscriptionDuration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("SubscriptionSince")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("SupportPending")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TokenValidTime")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("TotpEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("TotpSecret")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("DockerImages")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SharedDomainId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
|
||||||
|
b.Navigation("SharedDomain");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("Tags")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ImageId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("NodeId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NotificationClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("NotificationClient");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MainAllocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NodeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
|
||||||
|
b.Navigation("MainAllocation");
|
||||||
|
|
||||||
|
b.Navigation("Node");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Backups")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", null)
|
||||||
|
.WithMany("Limits")
|
||||||
|
.HasForeignKey("SubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Recipient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RecipientId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Sender")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SenderId");
|
||||||
|
|
||||||
|
b.Navigation("Recipient");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", "Subscription")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("Subscription");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("DockerImages");
|
||||||
|
|
||||||
|
b.Navigation("Tags");
|
||||||
|
|
||||||
|
b.Navigation("Variables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Allocations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Allocations");
|
||||||
|
|
||||||
|
b.Navigation("Backups");
|
||||||
|
|
||||||
|
b.Navigation("Variables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Limits");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedDatesToLogs : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "SecurityLog",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "ErrorLog",
|
||||||
|
type: "datetime(6)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "AuditLog",
|
||||||
|
type: "datetime(6)",
|
||||||
|
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: "SecurityLog");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "ErrorLog");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "AuditLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,31 +19,6 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
.HasAnnotation("ProductVersion", "7.0.3")
|
.HasAnnotation("ProductVersion", "7.0.3")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.AuditLogEntry", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("Ip")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext");
|
|
||||||
|
|
||||||
b.Property<string>("JsonData")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext");
|
|
||||||
|
|
||||||
b.Property<bool>("System")
|
|
||||||
.HasColumnType("tinyint(1)");
|
|
||||||
|
|
||||||
b.Property<int>("Type")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("AuditLog");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -220,6 +195,95 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
b.ToTable("LoadingMessages");
|
b.ToTable("LoadingMessages");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AuditLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Class")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Stacktrace")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ErrorLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SecurityLog");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|||||||
@@ -76,4 +76,16 @@ public static class Formatter
|
|||||||
|
|
||||||
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year} {i2s(e.Hour)}:{i2s(e.Minute)}";
|
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year} {i2s(e.Hour)}:{i2s(e.Minute)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FormatDateOnly(DateTime e)
|
||||||
|
{
|
||||||
|
string i2s(int i)
|
||||||
|
{
|
||||||
|
if (i.ToString().Length < 2)
|
||||||
|
return "0" + i;
|
||||||
|
return i.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public class WingsServerConverter
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
wingsServer.Settings.Skip_Egg_Scripts = false;
|
wingsServer.Settings.Skip_Egg_Scripts = false;
|
||||||
wingsServer.Settings.Suspended = false; //TODO: Implement
|
wingsServer.Settings.Suspended = server.Suspended;
|
||||||
wingsServer.Settings.Invocation = string.IsNullOrEmpty(server.OverrideStartup) ? image.Startup : server.OverrideStartup;
|
wingsServer.Settings.Invocation = string.IsNullOrEmpty(server.OverrideStartup) ? image.Startup : server.OverrideStartup;
|
||||||
wingsServer.Settings.Uuid = server.Uuid;
|
wingsServer.Settings.Uuid = server.Uuid;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class PullController : Controller
|
|||||||
Stream req = Request.Body;
|
Stream req = Request.Body;
|
||||||
string jwt = await new StreamReader(req).ReadToEndAsync();
|
string jwt = await new StreamReader(req).ReadToEndAsync();
|
||||||
|
|
||||||
var dict = OneTimeJwtService.Validate(jwt);
|
var dict = await OneTimeJwtService.Validate(jwt);
|
||||||
|
|
||||||
if (dict == null)
|
if (dict == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Logging.Net;
|
using Logging.Net;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
|
|
||||||
namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
||||||
|
|
||||||
@@ -7,12 +9,19 @@ namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
|||||||
[Route("api/moonlight/resources")]
|
[Route("api/moonlight/resources")]
|
||||||
public class ResourcesController : Controller
|
public class ResourcesController : Controller
|
||||||
{
|
{
|
||||||
|
private readonly SecurityLogService SecurityLogService;
|
||||||
|
|
||||||
|
public ResourcesController(SecurityLogService securityLogService)
|
||||||
|
{
|
||||||
|
SecurityLogService = securityLogService;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("images/{name}")]
|
[HttpGet("images/{name}")]
|
||||||
public ActionResult GetImage([FromRoute] string name)
|
public async Task<ActionResult> GetImage([FromRoute] string name)
|
||||||
{
|
{
|
||||||
if (name.Contains(".."))
|
if (name.Contains(".."))
|
||||||
{
|
{
|
||||||
//TODO: Add security warn
|
await SecurityLogService.Log(SecurityLogType.PathTransversal, name);
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,19 @@ public enum AuditLogType
|
|||||||
{
|
{
|
||||||
Login,
|
Login,
|
||||||
Register,
|
Register,
|
||||||
LoginFail
|
ChangePassword,
|
||||||
|
ChangePowerState,
|
||||||
|
CreateBackup,
|
||||||
|
RestoreBackup,
|
||||||
|
DeleteBackup,
|
||||||
|
DownloadBackup,
|
||||||
|
CreateServer,
|
||||||
|
ReinstallServer,
|
||||||
|
CancelSubscription,
|
||||||
|
ApplySubscriptionCode,
|
||||||
|
EnableTotp,
|
||||||
|
DisableTotp,
|
||||||
|
AddDomainRecord,
|
||||||
|
UpdateDomainRecord,
|
||||||
|
DeleteDomainRecord
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
public enum SecurityLogType
|
public enum SecurityLogType
|
||||||
{
|
{
|
||||||
ManipulatedJwt
|
ManipulatedJwt,
|
||||||
|
PathTransversal,
|
||||||
|
SftpBruteForce,
|
||||||
|
LoginFail
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,9 @@ using Logging.Net;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Exceptions;
|
using Moonlight.App.Exceptions;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Repositories.Domains;
|
using Moonlight.App.Repositories.Domains;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
using DnsRecord = Moonlight.App.Models.Misc.DnsRecord;
|
using DnsRecord = Moonlight.App.Models.Misc.DnsRecord;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
@@ -19,14 +21,18 @@ public class DomainService
|
|||||||
private readonly DomainRepository DomainRepository;
|
private readonly DomainRepository DomainRepository;
|
||||||
private readonly SharedDomainRepository SharedDomainRepository;
|
private readonly SharedDomainRepository SharedDomainRepository;
|
||||||
private readonly CloudFlareClient Client;
|
private readonly CloudFlareClient Client;
|
||||||
|
private readonly AuditLogService AuditLogService;
|
||||||
private readonly string AccountId;
|
private readonly string AccountId;
|
||||||
|
|
||||||
public DomainService(ConfigService configService,
|
public DomainService(
|
||||||
|
ConfigService configService,
|
||||||
DomainRepository domainRepository,
|
DomainRepository domainRepository,
|
||||||
SharedDomainRepository sharedDomainRepository)
|
SharedDomainRepository sharedDomainRepository,
|
||||||
|
AuditLogService auditLogService)
|
||||||
{
|
{
|
||||||
DomainRepository = domainRepository;
|
DomainRepository = domainRepository;
|
||||||
SharedDomainRepository = sharedDomainRepository;
|
SharedDomainRepository = sharedDomainRepository;
|
||||||
|
AuditLogService = auditLogService;
|
||||||
|
|
||||||
var config = configService
|
var config = configService
|
||||||
.GetSection("Moonlight")
|
.GetSection("Moonlight")
|
||||||
@@ -46,10 +52,10 @@ public class DomainService
|
|||||||
GetAvailableDomains() // This method returns all available domains which are not added as a shared domain
|
GetAvailableDomains() // This method returns all available domains which are not added as a shared domain
|
||||||
{
|
{
|
||||||
var domains = GetData(
|
var domains = GetData(
|
||||||
await Client.Zones.GetAsync(new()
|
await Client.Zones.GetAsync(new()
|
||||||
{
|
{
|
||||||
AccountId = AccountId
|
AccountId = AccountId
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
var sharedDomains = SharedDomainRepository.Get().ToArray();
|
var sharedDomains = SharedDomainRepository.Get().ToArray();
|
||||||
@@ -82,7 +88,7 @@ public class DomainService
|
|||||||
{
|
{
|
||||||
if (record.Name.EndsWith(dname))
|
if (record.Name.EndsWith(dname))
|
||||||
{
|
{
|
||||||
result.Add(new ()
|
result.Add(new()
|
||||||
{
|
{
|
||||||
Name = record.Name.Replace(dname, ""),
|
Name = record.Name.Replace(dname, ""),
|
||||||
Content = record.Content,
|
Content = record.Content,
|
||||||
@@ -95,7 +101,7 @@ public class DomainService
|
|||||||
}
|
}
|
||||||
else if (record.Name.EndsWith(rname))
|
else if (record.Name.EndsWith(rname))
|
||||||
{
|
{
|
||||||
result.Add(new ()
|
result.Add(new()
|
||||||
{
|
{
|
||||||
Name = record.Name.Replace(rname, ""),
|
Name = record.Name.Replace(rname, ""),
|
||||||
Content = record.Content,
|
Content = record.Content,
|
||||||
@@ -134,7 +140,6 @@ public class DomainService
|
|||||||
Type = dnsRecord.Type,
|
Type = dnsRecord.Type,
|
||||||
Data = new()
|
Data = new()
|
||||||
{
|
{
|
||||||
|
|
||||||
Service = parts[0],
|
Service = parts[0],
|
||||||
Protocol = protocol,
|
Protocol = protocol,
|
||||||
Name = name,
|
Name = name,
|
||||||
@@ -163,6 +168,8 @@ public class DomainService
|
|||||||
Name = name
|
Name = name
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.AddDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateDnsRecord(Domain d, DnsRecord dnsRecord)
|
public async Task UpdateDnsRecord(Domain d, DnsRecord dnsRecord)
|
||||||
@@ -174,21 +181,25 @@ public class DomainService
|
|||||||
|
|
||||||
if (dnsRecord.Type == DnsRecordType.Srv)
|
if (dnsRecord.Type == DnsRecordType.Srv)
|
||||||
{
|
{
|
||||||
throw new DisplayException("SRV records cannot be updated thanks to the cloudflare api client. Please delete the record and create a new one");
|
throw new DisplayException(
|
||||||
|
"SRV records cannot be updated thanks to the cloudflare api client. Please delete the record and create a new one");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var name = dnsRecord.Name == "" ? rname : dnsRecord.Name + dname;
|
var name = dnsRecord.Name == "" ? rname : dnsRecord.Name + dname;
|
||||||
|
|
||||||
GetData(await Client.Zones.DnsRecords.UpdateAsync(d.SharedDomain.CloudflareId, dnsRecord.Id, new ModifiedDnsRecord()
|
GetData(await Client.Zones.DnsRecords.UpdateAsync(d.SharedDomain.CloudflareId, dnsRecord.Id,
|
||||||
{
|
new ModifiedDnsRecord()
|
||||||
Content = dnsRecord.Content,
|
{
|
||||||
Proxied = dnsRecord.Proxied,
|
Content = dnsRecord.Content,
|
||||||
Ttl = dnsRecord.Ttl,
|
Proxied = dnsRecord.Proxied,
|
||||||
Name = name,
|
Ttl = dnsRecord.Ttl,
|
||||||
Type = dnsRecord.Type
|
Name = name,
|
||||||
}));
|
Type = dnsRecord.Type
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.UpdateDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteDnsRecord(Domain d, DnsRecord dnsRecord)
|
public async Task DeleteDnsRecord(Domain d, DnsRecord dnsRecord)
|
||||||
@@ -198,6 +209,8 @@ public class DomainService
|
|||||||
GetData(
|
GetData(
|
||||||
await Client.Zones.DnsRecords.DeleteAsync(domain.SharedDomain.CloudflareId, dnsRecord.Id)
|
await Client.Zones.DnsRecords.DeleteAsync(domain.SharedDomain.CloudflareId, dnsRecord.Id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.DeleteDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
private Domain EnsureData(Domain domain)
|
private Domain EnsureData(Domain domain)
|
||||||
@@ -210,6 +223,7 @@ public class DomainService
|
|||||||
.Include(x => x.SharedDomain)
|
.Include(x => x.SharedDomain)
|
||||||
.First(x => x.Id == domain.Id);
|
.First(x => x.Id == domain.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T GetData<T>(CloudFlareResult<T> result)
|
private T GetData<T>(CloudFlareResult<T> result)
|
||||||
{
|
{
|
||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ namespace Moonlight.App.Services.LogServices;
|
|||||||
public class AuditLogService
|
public class AuditLogService
|
||||||
{
|
{
|
||||||
private readonly AuditLogEntryRepository Repository;
|
private readonly AuditLogEntryRepository Repository;
|
||||||
private readonly IdentityService IdentityService;
|
private readonly IHttpContextAccessor HttpContextAccessor;
|
||||||
|
|
||||||
public AuditLogService(AuditLogEntryRepository repository, IdentityService identityService)
|
public AuditLogService(
|
||||||
|
AuditLogEntryRepository repository,
|
||||||
|
IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
Repository = repository;
|
Repository = repository;
|
||||||
IdentityService = identityService;
|
HttpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Log(AuditLogType type, object? data = null)
|
public Task Log(AuditLogType type, params object[] data)
|
||||||
{
|
{
|
||||||
var ip = IdentityService.GetIp();
|
var ip = GetIp();
|
||||||
|
|
||||||
var entry = new AuditLogEntry()
|
var entry = new AuditLogEntry()
|
||||||
{
|
{
|
||||||
Ip = ip,
|
Ip = ip,
|
||||||
Type = type,
|
Type = type,
|
||||||
System = false,
|
System = false,
|
||||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||||
};
|
};
|
||||||
|
|
||||||
Repository.Add(entry);
|
Repository.Add(entry);
|
||||||
@@ -34,17 +36,30 @@ public class AuditLogService
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LogSystem(AuditLogType type, object? data = null)
|
public Task LogSystem(AuditLogType type, params object[] data)
|
||||||
{
|
{
|
||||||
var entry = new AuditLogEntry()
|
var entry = new AuditLogEntry()
|
||||||
{
|
{
|
||||||
Type = type,
|
Type = type,
|
||||||
System = true,
|
System = true,
|
||||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||||
};
|
};
|
||||||
|
|
||||||
Repository.Add(entry);
|
Repository.Add(entry);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetIp()
|
||||||
|
{
|
||||||
|
if (HttpContextAccessor.HttpContext == null)
|
||||||
|
return "N/A";
|
||||||
|
|
||||||
|
if(HttpContextAccessor.HttpContext.Request.Headers.ContainsKey("X-Real-IP"))
|
||||||
|
{
|
||||||
|
return HttpContextAccessor.HttpContext.Request.Headers["X-Real-IP"]!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,17 +10,17 @@ namespace Moonlight.App.Services.LogServices;
|
|||||||
public class ErrorLogService
|
public class ErrorLogService
|
||||||
{
|
{
|
||||||
private readonly ErrorLogEntryRepository Repository;
|
private readonly ErrorLogEntryRepository Repository;
|
||||||
private readonly IdentityService IdentityService;
|
private readonly IHttpContextAccessor HttpContextAccessor;
|
||||||
|
|
||||||
public ErrorLogService(ErrorLogEntryRepository repository, IdentityService identityService)
|
public ErrorLogService(ErrorLogEntryRepository repository, IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
Repository = repository;
|
Repository = repository;
|
||||||
IdentityService = identityService;
|
HttpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Log(Exception exception, params object[] objects)
|
public Task Log(Exception exception, params object[] objects)
|
||||||
{
|
{
|
||||||
var ip = IdentityService.GetIp();
|
var ip = GetIp();
|
||||||
|
|
||||||
var entry = new ErrorLogEntry()
|
var entry = new ErrorLogEntry()
|
||||||
{
|
{
|
||||||
@@ -74,4 +74,17 @@ public class ErrorLogService
|
|||||||
|
|
||||||
return fullName;
|
return fullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetIp()
|
||||||
|
{
|
||||||
|
if (HttpContextAccessor.HttpContext == null)
|
||||||
|
return "N/A";
|
||||||
|
|
||||||
|
if(HttpContextAccessor.HttpContext.Request.Headers.ContainsKey("X-Real-IP"))
|
||||||
|
{
|
||||||
|
return HttpContextAccessor.HttpContext.Request.Headers["X-Real-IP"]!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,24 +9,24 @@ namespace Moonlight.App.Services.LogServices;
|
|||||||
public class SecurityLogService
|
public class SecurityLogService
|
||||||
{
|
{
|
||||||
private readonly SecurityLogEntryRepository Repository;
|
private readonly SecurityLogEntryRepository Repository;
|
||||||
private readonly IdentityService IdentityService;
|
private readonly IHttpContextAccessor HttpContextAccessor;
|
||||||
|
|
||||||
public SecurityLogService(SecurityLogEntryRepository repository, IdentityService identityService)
|
public SecurityLogService(SecurityLogEntryRepository repository, IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
Repository = repository;
|
Repository = repository;
|
||||||
IdentityService = identityService;
|
HttpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Log(SecurityLogType type, object? data = null)
|
public Task Log(SecurityLogType type, params object[] data)
|
||||||
{
|
{
|
||||||
var ip = IdentityService.GetIp();
|
var ip = GetIp();
|
||||||
|
|
||||||
var entry = new SecurityLogEntry()
|
var entry = new SecurityLogEntry()
|
||||||
{
|
{
|
||||||
Ip = ip,
|
Ip = ip,
|
||||||
Type = type,
|
Type = type,
|
||||||
System = false,
|
System = false,
|
||||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||||
};
|
};
|
||||||
|
|
||||||
Repository.Add(entry);
|
Repository.Add(entry);
|
||||||
@@ -34,17 +34,30 @@ public class SecurityLogService
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LogSystem(SecurityLogType type, object? data = null)
|
public Task LogSystem(SecurityLogType type, params object[] data)
|
||||||
{
|
{
|
||||||
var entry = new SecurityLogEntry()
|
var entry = new SecurityLogEntry()
|
||||||
{
|
{
|
||||||
Type = type,
|
Type = type,
|
||||||
System = true,
|
System = true,
|
||||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||||
};
|
};
|
||||||
|
|
||||||
Repository.Add(entry);
|
Repository.Add(entry);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetIp()
|
||||||
|
{
|
||||||
|
if (HttpContextAccessor.HttpContext == null)
|
||||||
|
return "N/A";
|
||||||
|
|
||||||
|
if(HttpContextAccessor.HttpContext.Request.Headers.ContainsKey("X-Real-IP"))
|
||||||
|
{
|
||||||
|
return HttpContextAccessor.HttpContext.Request.Headers["X-Real-IP"]!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,6 @@ public class MessageService : MessageSender
|
|||||||
{
|
{
|
||||||
public MessageService()
|
public MessageService()
|
||||||
{
|
{
|
||||||
Debug = true;
|
Debug = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using JWT.Algorithms;
|
using JWT.Algorithms;
|
||||||
using JWT.Builder;
|
using JWT.Builder;
|
||||||
|
using JWT.Exceptions;
|
||||||
using Moonlight.App.Exceptions;
|
using Moonlight.App.Exceptions;
|
||||||
using Moonlight.App.Helpers;
|
using Moonlight.App.Helpers;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
|
|
||||||
@@ -11,11 +14,15 @@ public class OneTimeJwtService
|
|||||||
{
|
{
|
||||||
private readonly ConfigService ConfigService;
|
private readonly ConfigService ConfigService;
|
||||||
private readonly RevokeRepository RevokeRepository;
|
private readonly RevokeRepository RevokeRepository;
|
||||||
|
private readonly SecurityLogService SecurityLogService;
|
||||||
|
|
||||||
public OneTimeJwtService(ConfigService configService, RevokeRepository revokeRepository)
|
public OneTimeJwtService(ConfigService configService,
|
||||||
|
RevokeRepository revokeRepository,
|
||||||
|
SecurityLogService securityLogService)
|
||||||
{
|
{
|
||||||
ConfigService = configService;
|
ConfigService = configService;
|
||||||
RevokeRepository = revokeRepository;
|
RevokeRepository = revokeRepository;
|
||||||
|
SecurityLogService = securityLogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Generate(Action<Dictionary<string, string>> options, TimeSpan? validTime = null)
|
public string Generate(Action<Dictionary<string, string>> options, TimeSpan? validTime = null)
|
||||||
@@ -51,7 +58,7 @@ public class OneTimeJwtService
|
|||||||
return builder.Encode();
|
return builder.Encode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, string>? Validate(string token)
|
public async Task<Dictionary<string, string>?> Validate(string token)
|
||||||
{
|
{
|
||||||
string secret = ConfigService
|
string secret = ConfigService
|
||||||
.GetSection("Moonlight")
|
.GetSection("Moonlight")
|
||||||
@@ -66,8 +73,11 @@ public class OneTimeJwtService
|
|||||||
.WithAlgorithm(new HMACSHA256Algorithm())
|
.WithAlgorithm(new HMACSHA256Algorithm())
|
||||||
.WithSecret(secret)
|
.WithSecret(secret)
|
||||||
.Decode(token);
|
.Decode(token);
|
||||||
|
}
|
||||||
//TODO: Error handling, report signature errors
|
catch (SignatureVerificationException)
|
||||||
|
{
|
||||||
|
await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, token);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -97,9 +107,9 @@ public class OneTimeJwtService
|
|||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Revoke(string token)
|
public async Task Revoke(string token)
|
||||||
{
|
{
|
||||||
var values = Validate(token);
|
var values = await Validate(token);
|
||||||
|
|
||||||
RevokeRepository.Add(new()
|
RevokeRepository.Add(new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ using Moonlight.App.Exceptions;
|
|||||||
using Moonlight.App.Helpers;
|
using Moonlight.App.Helpers;
|
||||||
using Moonlight.App.Models.Files;
|
using Moonlight.App.Models.Files;
|
||||||
using Moonlight.App.Models.Files.Accesses;
|
using Moonlight.App.Models.Files.Accesses;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Models.Wings;
|
using Moonlight.App.Models.Wings;
|
||||||
using Moonlight.App.Models.Wings.Requests;
|
using Moonlight.App.Models.Wings.Requests;
|
||||||
using Moonlight.App.Models.Wings.Resources;
|
using Moonlight.App.Models.Wings.Resources;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
using Moonlight.App.Repositories.Servers;
|
using Moonlight.App.Repositories.Servers;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
|
|
||||||
@@ -25,6 +27,9 @@ public class ServerService
|
|||||||
private readonly UserService UserService;
|
private readonly UserService UserService;
|
||||||
private readonly ConfigService ConfigService;
|
private readonly ConfigService ConfigService;
|
||||||
private readonly WingsJwtHelper WingsJwtHelper;
|
private readonly WingsJwtHelper WingsJwtHelper;
|
||||||
|
private readonly SecurityLogService SecurityLogService;
|
||||||
|
private readonly AuditLogService AuditLogService;
|
||||||
|
private readonly ErrorLogService ErrorLogService;
|
||||||
private readonly string AppUrl;
|
private readonly string AppUrl;
|
||||||
|
|
||||||
public ServerService(
|
public ServerService(
|
||||||
@@ -36,7 +41,10 @@ public class ServerService
|
|||||||
MessageService messageService,
|
MessageService messageService,
|
||||||
UserService userService,
|
UserService userService,
|
||||||
ConfigService configService,
|
ConfigService configService,
|
||||||
WingsJwtHelper wingsJwtHelper)
|
WingsJwtHelper wingsJwtHelper,
|
||||||
|
SecurityLogService securityLogService,
|
||||||
|
AuditLogService auditLogService,
|
||||||
|
ErrorLogService errorLogService)
|
||||||
{
|
{
|
||||||
ServerRepository = serverRepository;
|
ServerRepository = serverRepository;
|
||||||
WingsApiHelper = wingsApiHelper;
|
WingsApiHelper = wingsApiHelper;
|
||||||
@@ -47,6 +55,9 @@ public class ServerService
|
|||||||
UserService = userService;
|
UserService = userService;
|
||||||
ConfigService = configService;
|
ConfigService = configService;
|
||||||
WingsJwtHelper = wingsJwtHelper;
|
WingsJwtHelper = wingsJwtHelper;
|
||||||
|
SecurityLogService = securityLogService;
|
||||||
|
AuditLogService = auditLogService;
|
||||||
|
ErrorLogService = errorLogService;
|
||||||
|
|
||||||
AppUrl = ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl");
|
AppUrl = ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl");
|
||||||
}
|
}
|
||||||
@@ -84,6 +95,8 @@ public class ServerService
|
|||||||
{
|
{
|
||||||
Action = rawSignal
|
Action = rawSignal
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.ChangePowerState, new[] { server.Uuid.ToString(), rawSignal });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ServerBackup> CreateBackup(Server server)
|
public async Task<ServerBackup> CreateBackup(Server server)
|
||||||
@@ -112,6 +125,9 @@ public class ServerService
|
|||||||
Ignore = ""
|
Ignore = ""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.CreateBackup,
|
||||||
|
new[] { serverData.Uuid.ToString(), backup.Uuid.ToString() });
|
||||||
|
|
||||||
return backup;
|
return backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +162,9 @@ public class ServerService
|
|||||||
{
|
{
|
||||||
Adapter = "wings"
|
Adapter = "wings"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.RestoreBackup,
|
||||||
|
new[] { s.Uuid.ToString(), serverBackup.Uuid.ToString() });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteBackup(Server server, ServerBackup serverBackup)
|
public async Task DeleteBackup(Server server, ServerBackup serverBackup)
|
||||||
@@ -165,9 +184,12 @@ public class ServerService
|
|||||||
ServerRepository.Update(serverData);
|
ServerRepository.Update(serverData);
|
||||||
|
|
||||||
await MessageService.Emit("wings.backups.delete", backup);
|
await MessageService.Emit("wings.backups.delete", backup);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.DeleteBackup,
|
||||||
|
new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() });
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> DownloadBackup(Server s, ServerBackup serverBackup)
|
public async Task<string> DownloadBackup(Server s, ServerBackup serverBackup)
|
||||||
{
|
{
|
||||||
Server server = EnsureNodeData(s);
|
Server server = EnsureNodeData(s);
|
||||||
|
|
||||||
@@ -177,9 +199,10 @@ public class ServerService
|
|||||||
claims.Add("backup_uuid", serverBackup.Uuid.ToString());
|
claims.Add("backup_uuid", serverBackup.Uuid.ToString());
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.FromResult(
|
await AuditLogService.Log(AuditLogType.DownloadBackup,
|
||||||
$"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}"
|
new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() });
|
||||||
);
|
|
||||||
|
return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IFileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url
|
public Task<IFileAccess> CreateFileAccess(Server s, User user) // We need the user to create the launch url
|
||||||
@@ -197,7 +220,8 @@ public class ServerService
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Server> Create(string name, int cpu, long memory, long disk, User u, Image i, Node? n = null, Action<Server>? modifyDetails = null)
|
public async Task<Server> Create(string name, int cpu, long memory, long disk, User u, Image i, Node? n = null,
|
||||||
|
Action<Server>? modifyDetails = null)
|
||||||
{
|
{
|
||||||
var user = UserRepository
|
var user = UserRepository
|
||||||
.Get()
|
.Get()
|
||||||
@@ -268,7 +292,7 @@ public class ServerService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(modifyDetails != null)
|
if (modifyDetails != null)
|
||||||
modifyDetails.Invoke(server);
|
modifyDetails.Invoke(server);
|
||||||
|
|
||||||
var newServerData = ServerRepository.Add(server);
|
var newServerData = ServerRepository.Add(server);
|
||||||
@@ -281,16 +305,17 @@ public class ServerService
|
|||||||
StartOnCompletion = false
|
StartOnCompletion = false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.CreateServer, newServerData.Uuid.ToString());
|
||||||
|
|
||||||
return newServerData;
|
return newServerData;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Error("Error creating server on wings. Deleting db model");
|
await ErrorLogService.Log(e, new[] { newServerData.Uuid.ToString(), node.Id.ToString() });
|
||||||
Logger.Error(e);
|
|
||||||
|
|
||||||
ServerRepository.Delete(newServerData);
|
ServerRepository.Delete(newServerData);
|
||||||
|
|
||||||
throw new Exception("Error creating server on wings");
|
throw new DisplayException("Error creating server on wings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,14 +324,19 @@ public class ServerService
|
|||||||
Server server = EnsureNodeData(s);
|
Server server = EnsureNodeData(s);
|
||||||
|
|
||||||
await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/reinstall", null);
|
await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/reinstall", null);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.ReinstallServer, server.Uuid.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Server> SftpServerLogin(int serverId, int id, string password)
|
public async Task<Server> SftpServerLogin(int serverId, int id, string password)
|
||||||
{
|
{
|
||||||
var server = ServerRepository.Get().FirstOrDefault(x => x.Id == serverId);
|
var server = ServerRepository.Get().FirstOrDefault(x => x.Id == serverId);
|
||||||
|
|
||||||
if (server == null) //TODO: Logging
|
if (server == null)
|
||||||
|
{
|
||||||
|
await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, serverId);
|
||||||
throw new Exception("Server not found");
|
throw new Exception("Server not found");
|
||||||
|
}
|
||||||
|
|
||||||
var user = await UserService.SftpLogin(id, password);
|
var user = await UserService.SftpLogin(id, password);
|
||||||
|
|
||||||
@@ -316,6 +346,7 @@ public class ServerService
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//TODO: Decide if logging
|
||||||
throw new Exception("User and owner id do not match");
|
throw new Exception("User and owner id do not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ using JWT.Builder;
|
|||||||
using JWT.Exceptions;
|
using JWT.Exceptions;
|
||||||
using Logging.Net;
|
using Logging.Net;
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
using UAParser;
|
using UAParser;
|
||||||
|
|
||||||
namespace Moonlight.App.Services.Sessions;
|
namespace Moonlight.App.Services.Sessions;
|
||||||
@@ -13,6 +15,8 @@ public class IdentityService
|
|||||||
{
|
{
|
||||||
private readonly UserRepository UserRepository;
|
private readonly UserRepository UserRepository;
|
||||||
private readonly CookieService CookieService;
|
private readonly CookieService CookieService;
|
||||||
|
private readonly SecurityLogService SecurityLogService;
|
||||||
|
private readonly ErrorLogService ErrorLogService;
|
||||||
private readonly IHttpContextAccessor HttpContextAccessor;
|
private readonly IHttpContextAccessor HttpContextAccessor;
|
||||||
private readonly string Secret;
|
private readonly string Secret;
|
||||||
|
|
||||||
@@ -22,11 +26,15 @@ public class IdentityService
|
|||||||
CookieService cookieService,
|
CookieService cookieService,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
IHttpContextAccessor httpContextAccessor,
|
IHttpContextAccessor httpContextAccessor,
|
||||||
ConfigService configService)
|
ConfigService configService,
|
||||||
|
SecurityLogService securityLogService,
|
||||||
|
ErrorLogService errorLogService)
|
||||||
{
|
{
|
||||||
CookieService = cookieService;
|
CookieService = cookieService;
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
HttpContextAccessor = httpContextAccessor;
|
HttpContextAccessor = httpContextAccessor;
|
||||||
|
SecurityLogService = securityLogService;
|
||||||
|
ErrorLogService = errorLogService;
|
||||||
|
|
||||||
Secret = configService
|
Secret = configService
|
||||||
.GetSection("Moonlight")
|
.GetSection("Moonlight")
|
||||||
@@ -81,14 +89,12 @@ public class IdentityService
|
|||||||
}
|
}
|
||||||
catch (SignatureVerificationException)
|
catch (SignatureVerificationException)
|
||||||
{
|
{
|
||||||
//TODO: Heavy warn and write it to the logs
|
await SecurityLogService.Log(SecurityLogType.ManipulatedJwt, token);
|
||||||
Logger.Warn("Someone tried to modify his data: " + token);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warn("Error parsing and validating token");
|
await ErrorLogService.Log(e);
|
||||||
Logger.Warn(e);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,19 +123,14 @@ public class IdentityService
|
|||||||
var issuedAt = DateTimeOffset.FromUnixTimeSeconds(iat).DateTime;
|
var issuedAt = DateTimeOffset.FromUnixTimeSeconds(iat).DateTime;
|
||||||
|
|
||||||
if (issuedAt < user.TokenValidTime.ToUniversalTime())
|
if (issuedAt < user.TokenValidTime.ToUniversalTime())
|
||||||
{
|
|
||||||
//TODO: Remove at publish
|
|
||||||
//Logger.Debug($"Old token found: {issuedAt.ToShortDateString()} {issuedAt.ToShortTimeString()} Current valid token time {userData.TokenValidTime.ToUniversalTime().ToShortDateString()} {userData.TokenValidTime.ToUniversalTime().ToShortTimeString()}");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
UserCache = user;
|
UserCache = user;
|
||||||
return UserCache;
|
return UserCache;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warn("Error loading user");
|
await ErrorLogService.Log(e);
|
||||||
Logger.Warn(e);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Exceptions;
|
using Moonlight.App.Exceptions;
|
||||||
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
using Moonlight.App.Repositories.Subscriptions;
|
using Moonlight.App.Repositories.Subscriptions;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
using Moonlight.App.Services.Sessions;
|
using Moonlight.App.Services.Sessions;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
@@ -14,18 +16,21 @@ public class SubscriptionService
|
|||||||
private readonly IdentityService IdentityService;
|
private readonly IdentityService IdentityService;
|
||||||
private readonly ConfigService ConfigService;
|
private readonly ConfigService ConfigService;
|
||||||
private readonly OneTimeJwtService OneTimeJwtService;
|
private readonly OneTimeJwtService OneTimeJwtService;
|
||||||
|
private readonly AuditLogService AuditLogService;
|
||||||
|
|
||||||
public SubscriptionService(SubscriptionRepository subscriptionRepository,
|
public SubscriptionService(SubscriptionRepository subscriptionRepository,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
IdentityService identityService,
|
IdentityService identityService,
|
||||||
ConfigService configService,
|
ConfigService configService,
|
||||||
OneTimeJwtService oneTimeJwtService)
|
OneTimeJwtService oneTimeJwtService,
|
||||||
|
AuditLogService auditLogService)
|
||||||
{
|
{
|
||||||
SubscriptionRepository = subscriptionRepository;
|
SubscriptionRepository = subscriptionRepository;
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
IdentityService = identityService;
|
IdentityService = identityService;
|
||||||
ConfigService = configService;
|
ConfigService = configService;
|
||||||
OneTimeJwtService = oneTimeJwtService;
|
OneTimeJwtService = oneTimeJwtService;
|
||||||
|
AuditLogService = auditLogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Subscription?> Get()
|
public async Task<Subscription?> Get()
|
||||||
@@ -50,6 +55,8 @@ public class SubscriptionService
|
|||||||
var user = await IdentityService.Get();
|
var user = await IdentityService.Get();
|
||||||
user!.Subscription = null;
|
user!.Subscription = null;
|
||||||
UserRepository.Update(user!);
|
UserRepository.Update(user!);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.CancelSubscription, new[] { user.Email });
|
||||||
}
|
}
|
||||||
public Task<Subscription[]> GetAvailable()
|
public Task<Subscription[]> GetAvailable()
|
||||||
{
|
{
|
||||||
@@ -91,7 +98,7 @@ public class SubscriptionService
|
|||||||
public async Task ApplyCode(string code)
|
public async Task ApplyCode(string code)
|
||||||
{
|
{
|
||||||
var user = (await IdentityService.Get())!;
|
var user = (await IdentityService.Get())!;
|
||||||
var values = OneTimeJwtService.Validate(code);
|
var values = await OneTimeJwtService.Validate(code);
|
||||||
|
|
||||||
if (values == null)
|
if (values == null)
|
||||||
throw new DisplayException("Invalid subscription code");
|
throw new DisplayException("Invalid subscription code");
|
||||||
@@ -114,6 +121,8 @@ public class SubscriptionService
|
|||||||
|
|
||||||
UserRepository.Update(user);
|
UserRepository.Update(user);
|
||||||
|
|
||||||
OneTimeJwtService.Revoke(code);
|
await OneTimeJwtService.Revoke(code);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.ApplySubscriptionCode, new[] { user.Email, subscription.Id.ToString() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Models.Misc;
|
||||||
|
using Moonlight.App.Repositories;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
using Moonlight.App.Services.Sessions;
|
using Moonlight.App.Services.Sessions;
|
||||||
using OtpNet;
|
using OtpNet;
|
||||||
|
|
||||||
@@ -8,11 +10,16 @@ public class TotpService
|
|||||||
{
|
{
|
||||||
private readonly IdentityService IdentityService;
|
private readonly IdentityService IdentityService;
|
||||||
private readonly UserRepository UserRepository;
|
private readonly UserRepository UserRepository;
|
||||||
|
private readonly AuditLogService AuditLogService;
|
||||||
|
|
||||||
public TotpService(IdentityService identityService, UserRepository userRepository)
|
public TotpService(
|
||||||
|
IdentityService identityService,
|
||||||
|
UserRepository userRepository,
|
||||||
|
AuditLogService auditLogService)
|
||||||
{
|
{
|
||||||
IdentityService = identityService;
|
IdentityService = identityService;
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
|
AuditLogService = auditLogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> Verify(string secret, string code)
|
public Task<bool> Verify(string secret, string code)
|
||||||
@@ -38,21 +45,25 @@ public class TotpService
|
|||||||
|
|
||||||
public async Task Enable()
|
public async Task Enable()
|
||||||
{
|
{
|
||||||
var user = await IdentityService.Get();
|
var user = (await IdentityService.Get())!;
|
||||||
|
|
||||||
user.TotpEnabled = true;
|
user.TotpEnabled = true;
|
||||||
user.TotpSecret = GenerateSecret();
|
user.TotpSecret = GenerateSecret();
|
||||||
|
|
||||||
UserRepository.Update(user);
|
UserRepository.Update(user);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.EnableTotp, user.Email);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Disable()
|
public async Task Disable()
|
||||||
{
|
{
|
||||||
var user = await IdentityService.Get();
|
var user = (await IdentityService.Get())!;
|
||||||
|
|
||||||
user.TotpEnabled = false;
|
user.TotpEnabled = false;
|
||||||
|
|
||||||
UserRepository.Update(user);
|
UserRepository.Update(user);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.DisableTotp, user.Email);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateSecret()
|
private string GenerateSecret()
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using JWT.Algorithms;
|
using JWT.Algorithms;
|
||||||
using JWT.Builder;
|
using JWT.Builder;
|
||||||
using Logging.Net;
|
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Exceptions;
|
using Moonlight.App.Exceptions;
|
||||||
using Moonlight.App.Models.Misc;
|
using Moonlight.App.Models.Misc;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
|
|
||||||
@@ -12,20 +12,24 @@ public class UserService
|
|||||||
{
|
{
|
||||||
private readonly UserRepository UserRepository;
|
private readonly UserRepository UserRepository;
|
||||||
private readonly TotpService TotpService;
|
private readonly TotpService TotpService;
|
||||||
private readonly ConfigService ConfigService;
|
private readonly SecurityLogService SecurityLogService;
|
||||||
|
private readonly AuditLogService AuditLogService;
|
||||||
|
|
||||||
private readonly string JwtSecret;
|
private readonly string JwtSecret;
|
||||||
|
|
||||||
public UserService(
|
public UserService(
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
TotpService totpService,
|
TotpService totpService,
|
||||||
ConfigService configService)
|
ConfigService configService,
|
||||||
|
SecurityLogService securityLogService,
|
||||||
|
AuditLogService auditLogService)
|
||||||
{
|
{
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
TotpService = totpService;
|
TotpService = totpService;
|
||||||
ConfigService = configService;
|
SecurityLogService = securityLogService;
|
||||||
|
AuditLogService = auditLogService;
|
||||||
|
|
||||||
JwtSecret = ConfigService
|
JwtSecret = configService
|
||||||
.GetSection("Moonlight")
|
.GetSection("Moonlight")
|
||||||
.GetSection("Security")
|
.GetSection("Security")
|
||||||
.GetValue<string>("Token");
|
.GetValue<string>("Token");
|
||||||
@@ -68,10 +72,12 @@ public class UserService
|
|||||||
//var mail = new WelcomeMail(user);
|
//var mail = new WelcomeMail(user);
|
||||||
//await MailService.Send(mail, user);
|
//await MailService.Send(mail, user);
|
||||||
|
|
||||||
|
await AuditLogService.Log(AuditLogType.Register, user.Email);
|
||||||
|
|
||||||
return await GenerateToken(user);
|
return await GenerateToken(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> CheckTotp(string email, string password)
|
public async Task<bool> CheckTotp(string email, string password)
|
||||||
{
|
{
|
||||||
var user = UserRepository.Get()
|
var user = UserRepository.Get()
|
||||||
.FirstOrDefault(
|
.FirstOrDefault(
|
||||||
@@ -80,18 +86,16 @@ public class UserService
|
|||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
Logger.Debug("User not found");
|
await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password });
|
||||||
|
|
||||||
//AuditLogService.Log("login:fail", $"Invalid email: {email}. Password: {password}");
|
|
||||||
throw new DisplayException("Email and password combination not found");
|
throw new DisplayException("Email and password combination not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BCrypt.Net.BCrypt.Verify(password, user.Password))
|
if (BCrypt.Net.BCrypt.Verify(password, user.Password))
|
||||||
{
|
{
|
||||||
return Task.FromResult(user.TotpEnabled);
|
return user.TotpEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//AuditLogService.Log("login:fail", $"Invalid email: {email}. Password: {password}");
|
await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password });
|
||||||
throw new DisplayException("Email and password combination not found");;
|
throw new DisplayException("Email and password combination not found");;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,29 +115,27 @@ public class UserService
|
|||||||
if (string.IsNullOrEmpty(totpCode))
|
if (string.IsNullOrEmpty(totpCode))
|
||||||
throw new DisplayException("2FA code must be provided");
|
throw new DisplayException("2FA code must be provided");
|
||||||
|
|
||||||
var totpCodeValid = await TotpService.Verify(user.TotpSecret, totpCode);
|
var totpCodeValid = await TotpService.Verify(user!.TotpSecret, totpCode);
|
||||||
|
|
||||||
if (totpCodeValid)
|
if (totpCodeValid)
|
||||||
{
|
{
|
||||||
//AuditLogService.Log("login:success", $"{user.Email} has successfully logged in");
|
await AuditLogService.Log(AuditLogType.Login, email);
|
||||||
|
|
||||||
return await GenerateToken(user);
|
return await GenerateToken(user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//AuditLogService.Log("login:fail", $"Invalid totp code: {totpCode}");
|
await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password });
|
||||||
throw new DisplayException("2FA code invalid");
|
throw new DisplayException("2FA code invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//AuditLogService.Log("login:success", $"{user.Email} has successfully logged in");
|
await AuditLogService.Log(AuditLogType.Login, email);
|
||||||
|
|
||||||
return await GenerateToken(user!);
|
return await GenerateToken(user!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ChangePassword(User user, string password)
|
public async Task ChangePassword(User user, string password)
|
||||||
{
|
{
|
||||||
user.Password = BCrypt.Net.BCrypt.HashPassword(password);
|
user.Password = BCrypt.Net.BCrypt.HashPassword(password);
|
||||||
user.TokenValidTime = DateTime.Now;
|
user.TokenValidTime = DateTime.Now;
|
||||||
@@ -142,25 +144,26 @@ public class UserService
|
|||||||
//var mail = new NewPasswordMail(user);
|
//var mail = new NewPasswordMail(user);
|
||||||
//await MailService.Send(mail, user);
|
//await MailService.Send(mail, user);
|
||||||
|
|
||||||
//AuditLogService.Log("password:change", "The password has been set to a new one");
|
await AuditLogService.Log(AuditLogType.ChangePassword, user.Email);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<User> SftpLogin(int id, string password)
|
public async Task<User> SftpLogin(int id, string password)
|
||||||
{
|
{
|
||||||
var user = UserRepository.Get().FirstOrDefault(x => x.Id == id);
|
var user = UserRepository.Get().FirstOrDefault(x => x.Id == id);
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new Exception("Unknown user");
|
{
|
||||||
|
await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, id);
|
||||||
|
throw new Exception("Invalid username");
|
||||||
|
}
|
||||||
|
|
||||||
if (BCrypt.Net.BCrypt.Verify(password, user.Password))
|
if (BCrypt.Net.BCrypt.Verify(password, user.Password))
|
||||||
{
|
{
|
||||||
//TODO: Maybe log
|
await AuditLogService.LogSystem(AuditLogType.Login, user.Email);
|
||||||
return Task.FromResult(user);
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Log
|
await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, new[] { id.ToString(), password });
|
||||||
throw new Exception("Invalid userid or password");
|
throw new Exception("Invalid userid or password");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Moonlight.App.Repositories.Servers;
|
|||||||
using Moonlight.App.Repositories.Subscriptions;
|
using Moonlight.App.Repositories.Subscriptions;
|
||||||
using Moonlight.App.Services;
|
using Moonlight.App.Services;
|
||||||
using Moonlight.App.Services.Interop;
|
using Moonlight.App.Services.Interop;
|
||||||
|
using Moonlight.App.Services.LogServices;
|
||||||
using Moonlight.App.Services.Notifications;
|
using Moonlight.App.Services.Notifications;
|
||||||
using Moonlight.App.Services.OAuth2;
|
using Moonlight.App.Services.OAuth2;
|
||||||
using Moonlight.App.Services.Sessions;
|
using Moonlight.App.Services.Sessions;
|
||||||
@@ -80,7 +81,10 @@ namespace Moonlight
|
|||||||
builder.Services.AddScoped<GoogleOAuth2Service>();
|
builder.Services.AddScoped<GoogleOAuth2Service>();
|
||||||
builder.Services.AddScoped<DiscordOAuth2Service>();
|
builder.Services.AddScoped<DiscordOAuth2Service>();
|
||||||
|
|
||||||
|
// Loggers
|
||||||
|
builder.Services.AddScoped<SecurityLogService>();
|
||||||
|
builder.Services.AddScoped<AuditLogService>();
|
||||||
|
builder.Services.AddScoped<ErrorLogService>();
|
||||||
|
|
||||||
// Support
|
// Support
|
||||||
builder.Services.AddSingleton<SupportServerService>();
|
builder.Services.AddSingleton<SupportServerService>();
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
@using Moonlight.App.Database.Entities.LogsEntries
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Newtonsoft.Json
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
|
||||||
|
@inject UserRepository UserRepository
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-line w-40px"></div>
|
||||||
|
<div class="timeline-icon symbol symbol-circle symbol-40px">
|
||||||
|
<div class="symbol-label bg-light">
|
||||||
|
<i class="bx bx-md bx-log-in"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-content mb-10 mt-n2">
|
||||||
|
<div class="overflow-auto pe-3">
|
||||||
|
<div class="fs-5 fw-semibold mb-2">
|
||||||
|
@if (User == null)
|
||||||
|
{
|
||||||
|
<TL>Password change for</TL> @(Data[0])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<TL>Password change for</TL> <a href="/admin/users/view/@(User.Id)">@(User.Email)</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-1 fs-6">
|
||||||
|
<div class="text-muted me-2 fs-7">@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public AuditLogEntry Entry { get; set; }
|
||||||
|
|
||||||
|
private User? User;
|
||||||
|
private string[] Data;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Data = JsonConvert.DeserializeObject<string[]>(Entry.JsonData)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]);
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
@using Moonlight.App.Database.Entities.LogsEntries
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Newtonsoft.Json
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Repositories.Servers
|
||||||
|
|
||||||
|
@inject ServerRepository ServerRepository
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-line w-40px"></div>
|
||||||
|
<div class="timeline-icon symbol symbol-circle symbol-40px">
|
||||||
|
<div class="symbol-label bg-light">
|
||||||
|
<i class="bx bx-md bx-log-in"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-content mb-10 mt-n2">
|
||||||
|
<div class="overflow-auto pe-3">
|
||||||
|
<div class="fs-5 fw-semibold mb-2">
|
||||||
|
@if (Server == null)
|
||||||
|
{
|
||||||
|
<TL>Change power state for</TL> @(Data[0]) <TL>to</TL> @(Data[1])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<TL>Change power state for</TL> <a href="/admin/servers/edit/@(Server.Id)">@(Server.Name)</a> <TL>to</TL> @(Data[1])
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-1 fs-6">
|
||||||
|
<div class="text-muted me-2 fs-7">@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public AuditLogEntry Entry { get; set; }
|
||||||
|
|
||||||
|
private Server? Server;
|
||||||
|
private string[] Data;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Data = JsonConvert.DeserializeObject<string[]>(Entry.JsonData)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
Server = ServerRepository.Get().FirstOrDefault(x => x.Uuid == Guid.Parse(Data[0]));
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
@using Moonlight.App.Database.Entities.LogsEntries
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Newtonsoft.Json
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
|
||||||
|
@inject UserRepository UserRepository
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-line w-40px"></div>
|
||||||
|
<div class="timeline-icon symbol symbol-circle symbol-40px">
|
||||||
|
<div class="symbol-label bg-light">
|
||||||
|
<i class="bx bx-md bx-log-in"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-content mb-10 mt-n2">
|
||||||
|
<div class="overflow-auto pe-3">
|
||||||
|
<div class="fs-5 fw-semibold mb-2">
|
||||||
|
@if (User == null)
|
||||||
|
{
|
||||||
|
<TL>New login for</TL> @(Data[0])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<TL>New login for</TL> <a href="/admin/users/view/@(User.Id)">@(User.Email)</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-1 fs-6">
|
||||||
|
<div class="text-muted me-2 fs-7">@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public AuditLogEntry Entry { get; set; }
|
||||||
|
|
||||||
|
private User? User;
|
||||||
|
private string[] Data;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Data = JsonConvert.DeserializeObject<string[]>(Entry.JsonData)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]);
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
@using Moonlight.App.Database.Entities.LogsEntries
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Newtonsoft.Json
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
|
||||||
|
@inject UserRepository UserRepository
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-line w-40px"></div>
|
||||||
|
<div class="timeline-icon symbol symbol-circle symbol-40px">
|
||||||
|
<div class="symbol-label bg-light">
|
||||||
|
<i class="bx bx-md bx-log-in"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-content mb-10 mt-n2">
|
||||||
|
<div class="overflow-auto pe-3">
|
||||||
|
<div class="fs-5 fw-semibold mb-2">
|
||||||
|
@if (User == null)
|
||||||
|
{
|
||||||
|
<TL>Register for</TL> @(Data[0])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<TL>Register for</TL> <a href="/admin/users/view/@(User.Id)">@(User.Email)</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-1 fs-6">
|
||||||
|
<div class="text-muted me-2 fs-7">@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public AuditLogEntry Entry { get; set; }
|
||||||
|
|
||||||
|
private User? User;
|
||||||
|
private string[] Data;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Data = JsonConvert.DeserializeObject<string[]>(Entry.JsonData)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]);
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
@using Logging.Net
|
@using Logging.Net
|
||||||
|
@using Moonlight.App.Services.LogServices
|
||||||
@using Moonlight.App.Services.Sessions
|
@using Moonlight.App.Services.Sessions
|
||||||
|
|
||||||
@inherits ErrorBoundary
|
@inherits ErrorBoundary
|
||||||
|
|
||||||
@inject IdentityService IdentityService
|
@inject ErrorLogService ErrorLogService
|
||||||
|
|
||||||
@if (CurrentException is null)
|
@if (CurrentException is null)
|
||||||
{
|
{
|
||||||
@@ -52,13 +53,7 @@ else
|
|||||||
{
|
{
|
||||||
receivedExceptions.Add(exception);
|
receivedExceptions.Add(exception);
|
||||||
|
|
||||||
var user = await IdentityService.Get();
|
await ErrorLogService.Log(exception);
|
||||||
var id = user == null ? -1 : user.Id;
|
|
||||||
|
|
||||||
Logger.Error($"[{id}] An unhanded exception occured:");
|
|
||||||
Logger.Error(exception);
|
|
||||||
|
|
||||||
//TODO: Create error report
|
|
||||||
|
|
||||||
await base.OnErrorAsync(exception);
|
await base.OnErrorAsync(exception);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
{
|
{
|
||||||
protected override async Task OnErrorAsync(Exception exception)
|
protected override async Task OnErrorAsync(Exception exception)
|
||||||
{
|
{
|
||||||
|
Logger.Debug(exception);
|
||||||
|
|
||||||
if (exception is DisplayException displayException)
|
if (exception is DisplayException displayException)
|
||||||
{
|
{
|
||||||
await AlertService.Error(
|
await AlertService.Error(
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Models.Misc
|
||||||
|
|
||||||
|
<div class="card mb-5 mb-xl-10">
|
||||||
|
<div class="card-body pt-0 pb-0">
|
||||||
|
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/system">
|
||||||
|
Overview
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/system/auditlog">
|
||||||
|
AuditLog
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Index { get; set; } = 0;
|
||||||
|
}
|
||||||
@@ -93,7 +93,7 @@ else
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-item">
|
<div class="menu-item">
|
||||||
<a class="menu-link" href="/admin/general">
|
<a class="menu-link" href="/admin/system">
|
||||||
<span class="menu-icon">
|
<span class="menu-icon">
|
||||||
<i class="bx bx-chip"></i>
|
<i class="bx bx-chip"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -44,11 +44,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<WorkerButton
|
<WButton
|
||||||
OnClick="Save"
|
OnClick="Save"
|
||||||
Text="@(TranslationService.Translate("Change"))"
|
Text="@(TranslationService.Translate("Change"))"
|
||||||
WorkingText="@(TranslationService.Translate("Changing"))"
|
WorkingText="@(TranslationService.Translate("Changing"))"
|
||||||
CssClasses="btn-primary"></WorkerButton>
|
CssClasses="btn-primary"></WButton>
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
106
Moonlight/Shared/Views/Admin/Sys/AuditLog.razor
Normal file
106
Moonlight/Shared/Views/Admin/Sys/AuditLog.razor
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
@page "/admin/system/auditlog"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
@using Moonlight.App.Repositories.LogEntries
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.App.Database.Entities.LogsEntries
|
||||||
|
@using BlazorTable
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Moonlight.App.Models.Misc
|
||||||
|
@using Moonlight.Shared.Components.AuditLogEntrys
|
||||||
|
|
||||||
|
@inject AuditLogEntryRepository AuditLogEntryRepository
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminSystemNavigation Index="1"/>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header card-header-stretch">
|
||||||
|
<div class="card-title d-flex align-items-center">
|
||||||
|
<span class="me-3 lh-0">
|
||||||
|
<i class="bx bx-md bx-calendar"></i>
|
||||||
|
</span>
|
||||||
|
<h3 class="fw-bold m-0 text-gray-800">@(Formatter.FormatDateOnly(DateTime))</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-toolbar m-0">
|
||||||
|
<ul class="nav nav-tabs nav-line-tabs nav-stretch fs-6 border-0 fw-bold">
|
||||||
|
<li class="nav-item">
|
||||||
|
<button @onclick="Left" class="nav-link justify-content-center text-active-gray-800">
|
||||||
|
<i class="bx bx-md bx-left-arrow"></i>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button @onclick="Right" class="nav-link justify-content-center text-active-gray-800">
|
||||||
|
<i class="bx bx-md bx-right-arrow"></i>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
@if (AuditLogEntries.Any())
|
||||||
|
{
|
||||||
|
<div class="timeline">
|
||||||
|
@foreach (var entry in AuditLogEntries)
|
||||||
|
{
|
||||||
|
switch (entry.Type)
|
||||||
|
{
|
||||||
|
case AuditLogType.Login:
|
||||||
|
<AuditLogEntryLogin Entry="entry"/>
|
||||||
|
break;
|
||||||
|
case AuditLogType.Register:
|
||||||
|
<AuditLogEntryRegister Entry="entry"/>
|
||||||
|
break;
|
||||||
|
case AuditLogType.ChangePassword:
|
||||||
|
<AuditLogEntryChangePassword Entry="entry"/>
|
||||||
|
break;
|
||||||
|
case AuditLogType.ChangePowerState:
|
||||||
|
<AuditLogEntryChangePowerState Entry="entry"/>
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-primary">
|
||||||
|
<TL>No records found for this day</TL>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private AuditLogEntry[] AuditLogEntries;
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
private DateTime DateTime = DateTime.Today;
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
AuditLogEntries = AuditLogEntryRepository
|
||||||
|
.Get()
|
||||||
|
.Where(x => x.CreatedAt.Date == DateTime.Date)
|
||||||
|
.OrderByDescending(x => x.Id)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Left()
|
||||||
|
{
|
||||||
|
DateTime = DateTime.AddDays(1);
|
||||||
|
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Right()
|
||||||
|
{
|
||||||
|
DateTime = DateTime.AddDays(-1);
|
||||||
|
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Moonlight/Shared/Views/Admin/Sys/Index.razor
Normal file
9
Moonlight/Shared/Views/Admin/Sys/Index.razor
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@page "/admin/system"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminSystemNavigation Index="0" />
|
||||||
|
|
||||||
|
|
||||||
|
</OnlyAdmin>
|
||||||
@@ -31,6 +31,10 @@ build_metadata.AdditionalFiles.CssScope =
|
|||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQWxlcnRzXFNldHVwQ29tcGxldGVkQWxlcnQucmF6b3I=
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQWxlcnRzXFNldHVwQ29tcGxldGVkQWxlcnQucmF6b3I=
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor]
|
||||||
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQXVkaXRMb2dFbnRyeXNcQXVkaXRMb2dFbnRyeUxvZ2luLnJhem9y
|
||||||
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/Auth/Login.razor]
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/Auth/Login.razor]
|
||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQXV0aFxMb2dpbi5yYXpvcg==
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQXV0aFxMb2dpbi5yYXpvcg==
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
@@ -67,6 +71,10 @@ build_metadata.AdditionalFiles.CssScope =
|
|||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRm9ybXNcV0J1dHRvbi5yYXpvcg==
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRm9ybXNcV0J1dHRvbi5yYXpvcg==
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/Navigations/AdminSystemNavigation.razor]
|
||||||
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcTmF2aWdhdGlvbnNcQWRtaW5TeXN0ZW1OYXZpZ2F0aW9uLnJhem9y
|
||||||
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor]
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Components/Navigations/ProfileNavigation.razor]
|
||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcTmF2aWdhdGlvbnNcUHJvZmlsZU5hdmlnYXRpb24ucmF6b3I=
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcTmF2aWdhdGlvbnNcUHJvZmlsZU5hdmlnYXRpb24ucmF6b3I=
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
@@ -227,6 +235,18 @@ build_metadata.AdditionalFiles.CssScope =
|
|||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN1cHBvcnRcVmlldy5yYXpvcg==
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN1cHBvcnRcVmlldy5yYXpvcg==
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Views/Admin/Sys/AuditLog.razor]
|
||||||
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN5c1xBdWRpdExvZy5yYXpvcg==
|
||||||
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Views/Admin/Sys/Index.razor]
|
||||||
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN5c1xJbmRleC5yYXpvcg==
|
||||||
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Views/Admin/Sys/Logging.razor]
|
||||||
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN5c1xMb2dnaW5nLnJhem9y
|
||||||
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|
||||||
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Views/Domains.razor]
|
[C:/Users/marce/GitHub/Moonlight-Panel/Moonlight/Moonlight/Shared/Views/Domains.razor]
|
||||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXERvbWFpbnMucmF6b3I=
|
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXERvbWFpbnMucmF6b3I=
|
||||||
build_metadata.AdditionalFiles.CssScope =
|
build_metadata.AdditionalFiles.CssScope =
|
||||||
|
|||||||
@@ -257,3 +257,13 @@ Cancel Subscription;Cancel Subscription
|
|||||||
Active until;Active until
|
Active until;Active until
|
||||||
We will send you a notification upon subscription expiration;We will send you a notification upon subscription expiration
|
We will send you a notification upon subscription expiration;We will send you a notification upon subscription expiration
|
||||||
This token has been already used;This token has been already used
|
This token has been already used;This token has been already used
|
||||||
|
New login for;New login for
|
||||||
|
No records found for this day;No records found for this day
|
||||||
|
Change;Change
|
||||||
|
Changing;Changing
|
||||||
|
Minecraft version;Minecraft version
|
||||||
|
Build version;Build version
|
||||||
|
Server installation is currently running;Server installation is currently running
|
||||||
|
Selected;Selected
|
||||||
|
Move deleted;Move deleted
|
||||||
|
Delete selected;Delete selected
|
||||||
|
|||||||
Reference in New Issue
Block a user