Added audit logging. Added admin view for audit log
This commit is contained in:
parent
d7b10aa224
commit
62cd63f56b
39 changed files with 2754 additions and 153 deletions
|
@ -9,4 +9,5 @@ public class AuditLogEntry
|
|||
public string JsonData { get; set; } = "";
|
||||
public bool System { 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 Ip { 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 SecurityLogType Type { 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("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 =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -220,6 +195,95 @@ namespace Moonlight.App.Database.Migrations
|
|||
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")
|
||||
|
|
|
@ -76,4 +76,16 @@ public static class Formatter
|
|||
|
||||
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
|
||||
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.Uuid = server.Uuid;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public class PullController : Controller
|
|||
Stream req = Request.Body;
|
||||
string jwt = await new StreamReader(req).ReadToEndAsync();
|
||||
|
||||
var dict = OneTimeJwtService.Validate(jwt);
|
||||
var dict = await OneTimeJwtService.Validate(jwt);
|
||||
|
||||
if (dict == null)
|
||||
return NotFound();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Logging.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
||||
|
||||
|
@ -7,12 +9,19 @@ namespace Moonlight.App.Http.Controllers.Api.Moonlight;
|
|||
[Route("api/moonlight/resources")]
|
||||
public class ResourcesController : Controller
|
||||
{
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
|
||||
public ResourcesController(SecurityLogService securityLogService)
|
||||
{
|
||||
SecurityLogService = securityLogService;
|
||||
}
|
||||
|
||||
[HttpGet("images/{name}")]
|
||||
public ActionResult GetImage([FromRoute] string name)
|
||||
public async Task<ActionResult> GetImage([FromRoute] string name)
|
||||
{
|
||||
if (name.Contains(".."))
|
||||
{
|
||||
//TODO: Add security warn
|
||||
await SecurityLogService.Log(SecurityLogType.PathTransversal, name);
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,5 +4,19 @@ public enum AuditLogType
|
|||
{
|
||||
Login,
|
||||
Register,
|
||||
LoginFail
|
||||
ChangePassword,
|
||||
ChangePowerState,
|
||||
CreateBackup,
|
||||
RestoreBackup,
|
||||
DeleteBackup,
|
||||
DownloadBackup,
|
||||
CreateServer,
|
||||
ReinstallServer,
|
||||
CancelSubscription,
|
||||
ApplySubscriptionCode,
|
||||
EnableTotp,
|
||||
DisableTotp,
|
||||
AddDomainRecord,
|
||||
UpdateDomainRecord,
|
||||
DeleteDomainRecord
|
||||
}
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
public enum SecurityLogType
|
||||
{
|
||||
ManipulatedJwt
|
||||
ManipulatedJwt,
|
||||
PathTransversal,
|
||||
SftpBruteForce,
|
||||
LoginFail
|
||||
}
|
|
@ -9,7 +9,9 @@ using Logging.Net;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Repositories.Domains;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
using DnsRecord = Moonlight.App.Models.Misc.DnsRecord;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
@ -19,14 +21,18 @@ public class DomainService
|
|||
private readonly DomainRepository DomainRepository;
|
||||
private readonly SharedDomainRepository SharedDomainRepository;
|
||||
private readonly CloudFlareClient Client;
|
||||
private readonly AuditLogService AuditLogService;
|
||||
private readonly string AccountId;
|
||||
|
||||
public DomainService(ConfigService configService,
|
||||
public DomainService(
|
||||
ConfigService configService,
|
||||
DomainRepository domainRepository,
|
||||
SharedDomainRepository sharedDomainRepository)
|
||||
SharedDomainRepository sharedDomainRepository,
|
||||
AuditLogService auditLogService)
|
||||
{
|
||||
DomainRepository = domainRepository;
|
||||
SharedDomainRepository = sharedDomainRepository;
|
||||
AuditLogService = auditLogService;
|
||||
|
||||
var config = configService
|
||||
.GetSection("Moonlight")
|
||||
|
@ -46,10 +52,10 @@ public class DomainService
|
|||
GetAvailableDomains() // This method returns all available domains which are not added as a shared domain
|
||||
{
|
||||
var domains = GetData(
|
||||
await Client.Zones.GetAsync(new()
|
||||
{
|
||||
AccountId = AccountId
|
||||
})
|
||||
await Client.Zones.GetAsync(new()
|
||||
{
|
||||
AccountId = AccountId
|
||||
})
|
||||
);
|
||||
|
||||
var sharedDomains = SharedDomainRepository.Get().ToArray();
|
||||
|
@ -82,7 +88,7 @@ public class DomainService
|
|||
{
|
||||
if (record.Name.EndsWith(dname))
|
||||
{
|
||||
result.Add(new ()
|
||||
result.Add(new()
|
||||
{
|
||||
Name = record.Name.Replace(dname, ""),
|
||||
Content = record.Content,
|
||||
|
@ -95,7 +101,7 @@ public class DomainService
|
|||
}
|
||||
else if (record.Name.EndsWith(rname))
|
||||
{
|
||||
result.Add(new ()
|
||||
result.Add(new()
|
||||
{
|
||||
Name = record.Name.Replace(rname, ""),
|
||||
Content = record.Content,
|
||||
|
@ -107,14 +113,14 @@ public class DomainService
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public async Task AddDnsRecord(Domain d, DnsRecord dnsRecord)
|
||||
{
|
||||
var domain = EnsureData(d);
|
||||
|
||||
|
||||
var rname = $"{domain.Name}.{domain.SharedDomain.Name}";
|
||||
var dname = $".{rname}";
|
||||
|
||||
|
@ -134,7 +140,6 @@ public class DomainService
|
|||
Type = dnsRecord.Type,
|
||||
Data = new()
|
||||
{
|
||||
|
||||
Service = parts[0],
|
||||
Protocol = protocol,
|
||||
Name = name,
|
||||
|
@ -146,7 +151,7 @@ public class DomainService
|
|||
Proxied = dnsRecord.Proxied,
|
||||
Ttl = dnsRecord.Ttl,
|
||||
};
|
||||
|
||||
|
||||
GetData(await Client.Zones.DnsRecords.AddAsync(d.SharedDomain.CloudflareId, srv));
|
||||
}
|
||||
else
|
||||
|
@ -163,32 +168,38 @@ public class DomainService
|
|||
Name = name
|
||||
}));
|
||||
}
|
||||
|
||||
await AuditLogService.Log(AuditLogType.AddDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name });
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateDnsRecord(Domain d, DnsRecord dnsRecord)
|
||||
{
|
||||
var domain = EnsureData(d);
|
||||
|
||||
|
||||
var rname = $"{domain.Name}.{domain.SharedDomain.Name}";
|
||||
var dname = $".{rname}";
|
||||
|
||||
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
|
||||
{
|
||||
var name = dnsRecord.Name == "" ? rname : dnsRecord.Name + dname;
|
||||
|
||||
GetData(await Client.Zones.DnsRecords.UpdateAsync(d.SharedDomain.CloudflareId, dnsRecord.Id, new ModifiedDnsRecord()
|
||||
{
|
||||
Content = dnsRecord.Content,
|
||||
Proxied = dnsRecord.Proxied,
|
||||
Ttl = dnsRecord.Ttl,
|
||||
Name = name,
|
||||
Type = dnsRecord.Type
|
||||
}));
|
||||
|
||||
GetData(await Client.Zones.DnsRecords.UpdateAsync(d.SharedDomain.CloudflareId, dnsRecord.Id,
|
||||
new ModifiedDnsRecord()
|
||||
{
|
||||
Content = dnsRecord.Content,
|
||||
Proxied = dnsRecord.Proxied,
|
||||
Ttl = dnsRecord.Ttl,
|
||||
Name = name,
|
||||
Type = dnsRecord.Type
|
||||
}));
|
||||
}
|
||||
|
||||
await AuditLogService.Log(AuditLogType.UpdateDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name });
|
||||
}
|
||||
|
||||
public async Task DeleteDnsRecord(Domain d, DnsRecord dnsRecord)
|
||||
|
@ -198,6 +209,8 @@ public class DomainService
|
|||
GetData(
|
||||
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)
|
||||
|
@ -210,12 +223,13 @@ public class DomainService
|
|||
.Include(x => x.SharedDomain)
|
||||
.First(x => x.Id == domain.Id);
|
||||
}
|
||||
|
||||
private T GetData<T>(CloudFlareResult<T> result)
|
||||
{
|
||||
if (!result.Success)
|
||||
{
|
||||
string message;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
message = result.Errors.First().ErrorChain.First().Message;
|
||||
|
|
|
@ -9,24 +9,26 @@ namespace Moonlight.App.Services.LogServices;
|
|||
public class AuditLogService
|
||||
{
|
||||
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;
|
||||
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()
|
||||
{
|
||||
Ip = ip,
|
||||
Type = type,
|
||||
System = false,
|
||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
||||
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||
};
|
||||
|
||||
Repository.Add(entry);
|
||||
|
@ -34,17 +36,30 @@ public class AuditLogService
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task LogSystem(AuditLogType type, object? data = null)
|
||||
public Task LogSystem(AuditLogType type, params object[] data)
|
||||
{
|
||||
var entry = new AuditLogEntry()
|
||||
{
|
||||
Type = type,
|
||||
System = true,
|
||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
||||
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||
};
|
||||
|
||||
Repository.Add(entry);
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
IdentityService = identityService;
|
||||
HttpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public Task Log(Exception exception, params object[] objects)
|
||||
{
|
||||
var ip = IdentityService.GetIp();
|
||||
var ip = GetIp();
|
||||
|
||||
var entry = new ErrorLogEntry()
|
||||
{
|
||||
|
@ -74,4 +74,17 @@ public class ErrorLogService
|
|||
|
||||
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
|
||||
{
|
||||
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;
|
||||
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()
|
||||
{
|
||||
Ip = ip,
|
||||
Type = type,
|
||||
System = false,
|
||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
||||
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||
};
|
||||
|
||||
Repository.Add(entry);
|
||||
|
@ -34,17 +34,30 @@ public class SecurityLogService
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task LogSystem(SecurityLogType type, object? data = null)
|
||||
public Task LogSystem(SecurityLogType type, params object[] data)
|
||||
{
|
||||
var entry = new SecurityLogEntry()
|
||||
{
|
||||
Type = type,
|
||||
System = true,
|
||||
JsonData = data == null ? "" : JsonConvert.SerializeObject(data)
|
||||
JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data)
|
||||
};
|
||||
|
||||
Repository.Add(entry);
|
||||
|
||||
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()
|
||||
{
|
||||
Debug = true;
|
||||
Debug = false;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using System.Text;
|
||||
using JWT.Algorithms;
|
||||
using JWT.Builder;
|
||||
using JWT.Exceptions;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
||||
|
@ -11,11 +14,15 @@ public class OneTimeJwtService
|
|||
{
|
||||
private readonly ConfigService ConfigService;
|
||||
private readonly RevokeRepository RevokeRepository;
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
|
||||
public OneTimeJwtService(ConfigService configService, RevokeRepository revokeRepository)
|
||||
public OneTimeJwtService(ConfigService configService,
|
||||
RevokeRepository revokeRepository,
|
||||
SecurityLogService securityLogService)
|
||||
{
|
||||
ConfigService = configService;
|
||||
RevokeRepository = revokeRepository;
|
||||
SecurityLogService = securityLogService;
|
||||
}
|
||||
|
||||
public string Generate(Action<Dictionary<string, string>> options, TimeSpan? validTime = null)
|
||||
|
@ -51,7 +58,7 @@ public class OneTimeJwtService
|
|||
return builder.Encode();
|
||||
}
|
||||
|
||||
public Dictionary<string, string>? Validate(string token)
|
||||
public async Task<Dictionary<string, string>?> Validate(string token)
|
||||
{
|
||||
string secret = ConfigService
|
||||
.GetSection("Moonlight")
|
||||
|
@ -59,15 +66,18 @@ public class OneTimeJwtService
|
|||
.GetValue<string>("Token");
|
||||
|
||||
string json;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
json = JwtBuilder.Create()
|
||||
.WithAlgorithm(new HMACSHA256Algorithm())
|
||||
.WithSecret(secret)
|
||||
.Decode(token);
|
||||
|
||||
//TODO: Error handling, report signature errors
|
||||
}
|
||||
catch (SignatureVerificationException)
|
||||
{
|
||||
await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, token);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -97,9 +107,9 @@ public class OneTimeJwtService
|
|||
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()
|
||||
{
|
||||
|
|
|
@ -6,11 +6,13 @@ using Moonlight.App.Exceptions;
|
|||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Files;
|
||||
using Moonlight.App.Models.Files.Accesses;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Models.Wings;
|
||||
using Moonlight.App.Models.Wings.Requests;
|
||||
using Moonlight.App.Models.Wings.Resources;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Repositories.Servers;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
||||
|
@ -25,6 +27,9 @@ public class ServerService
|
|||
private readonly UserService UserService;
|
||||
private readonly ConfigService ConfigService;
|
||||
private readonly WingsJwtHelper WingsJwtHelper;
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
private readonly AuditLogService AuditLogService;
|
||||
private readonly ErrorLogService ErrorLogService;
|
||||
private readonly string AppUrl;
|
||||
|
||||
public ServerService(
|
||||
|
@ -36,7 +41,10 @@ public class ServerService
|
|||
MessageService messageService,
|
||||
UserService userService,
|
||||
ConfigService configService,
|
||||
WingsJwtHelper wingsJwtHelper)
|
||||
WingsJwtHelper wingsJwtHelper,
|
||||
SecurityLogService securityLogService,
|
||||
AuditLogService auditLogService,
|
||||
ErrorLogService errorLogService)
|
||||
{
|
||||
ServerRepository = serverRepository;
|
||||
WingsApiHelper = wingsApiHelper;
|
||||
|
@ -47,6 +55,9 @@ public class ServerService
|
|||
UserService = userService;
|
||||
ConfigService = configService;
|
||||
WingsJwtHelper = wingsJwtHelper;
|
||||
SecurityLogService = securityLogService;
|
||||
AuditLogService = auditLogService;
|
||||
ErrorLogService = errorLogService;
|
||||
|
||||
AppUrl = ConfigService.GetSection("Moonlight").GetValue<string>("AppUrl");
|
||||
}
|
||||
|
@ -84,6 +95,8 @@ public class ServerService
|
|||
{
|
||||
Action = rawSignal
|
||||
});
|
||||
|
||||
await AuditLogService.Log(AuditLogType.ChangePowerState, new[] { server.Uuid.ToString(), rawSignal });
|
||||
}
|
||||
|
||||
public async Task<ServerBackup> CreateBackup(Server server)
|
||||
|
@ -112,6 +125,9 @@ public class ServerService
|
|||
Ignore = ""
|
||||
});
|
||||
|
||||
await AuditLogService.Log(AuditLogType.CreateBackup,
|
||||
new[] { serverData.Uuid.ToString(), backup.Uuid.ToString() });
|
||||
|
||||
return backup;
|
||||
}
|
||||
|
||||
|
@ -146,6 +162,9 @@ public class ServerService
|
|||
{
|
||||
Adapter = "wings"
|
||||
});
|
||||
|
||||
await AuditLogService.Log(AuditLogType.RestoreBackup,
|
||||
new[] { s.Uuid.ToString(), serverBackup.Uuid.ToString() });
|
||||
}
|
||||
|
||||
public async Task DeleteBackup(Server server, ServerBackup serverBackup)
|
||||
|
@ -165,9 +184,12 @@ public class ServerService
|
|||
ServerRepository.Update(serverData);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -176,10 +198,11 @@ public class ServerService
|
|||
claims.Add("server_uuid", server.Uuid.ToString());
|
||||
claims.Add("backup_uuid", serverBackup.Uuid.ToString());
|
||||
});
|
||||
|
||||
await AuditLogService.Log(AuditLogType.DownloadBackup,
|
||||
new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() });
|
||||
|
||||
return Task.FromResult(
|
||||
$"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}"
|
||||
);
|
||||
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
|
||||
|
@ -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
|
||||
.Get()
|
||||
|
@ -267,8 +291,8 @@ public class ServerService
|
|||
Value = imageVariable.DefaultValue
|
||||
});
|
||||
}
|
||||
|
||||
if(modifyDetails != null)
|
||||
|
||||
if (modifyDetails != null)
|
||||
modifyDetails.Invoke(server);
|
||||
|
||||
var newServerData = ServerRepository.Add(server);
|
||||
|
@ -281,16 +305,17 @@ public class ServerService
|
|||
StartOnCompletion = false
|
||||
});
|
||||
|
||||
await AuditLogService.Log(AuditLogType.CreateServer, newServerData.Uuid.ToString());
|
||||
|
||||
return newServerData;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("Error creating server on wings. Deleting db model");
|
||||
Logger.Error(e);
|
||||
await ErrorLogService.Log(e, new[] { newServerData.Uuid.ToString(), node.Id.ToString() });
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
var user = await UserService.SftpLogin(id, password);
|
||||
|
||||
|
@ -316,6 +346,7 @@ public class ServerService
|
|||
}
|
||||
else
|
||||
{
|
||||
//TODO: Decide if logging
|
||||
throw new Exception("User and owner id do not match");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ using JWT.Builder;
|
|||
using JWT.Exceptions;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
using UAParser;
|
||||
|
||||
namespace Moonlight.App.Services.Sessions;
|
||||
|
@ -13,6 +15,8 @@ public class IdentityService
|
|||
{
|
||||
private readonly UserRepository UserRepository;
|
||||
private readonly CookieService CookieService;
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
private readonly ErrorLogService ErrorLogService;
|
||||
private readonly IHttpContextAccessor HttpContextAccessor;
|
||||
private readonly string Secret;
|
||||
|
||||
|
@ -22,11 +26,15 @@ public class IdentityService
|
|||
CookieService cookieService,
|
||||
UserRepository userRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ConfigService configService)
|
||||
ConfigService configService,
|
||||
SecurityLogService securityLogService,
|
||||
ErrorLogService errorLogService)
|
||||
{
|
||||
CookieService = cookieService;
|
||||
UserRepository = userRepository;
|
||||
HttpContextAccessor = httpContextAccessor;
|
||||
SecurityLogService = securityLogService;
|
||||
ErrorLogService = errorLogService;
|
||||
|
||||
Secret = configService
|
||||
.GetSection("Moonlight")
|
||||
|
@ -81,14 +89,12 @@ public class IdentityService
|
|||
}
|
||||
catch (SignatureVerificationException)
|
||||
{
|
||||
//TODO: Heavy warn and write it to the logs
|
||||
Logger.Warn("Someone tried to modify his data: " + token);
|
||||
await SecurityLogService.Log(SecurityLogType.ManipulatedJwt, token);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warn("Error parsing and validating token");
|
||||
Logger.Warn(e);
|
||||
await ErrorLogService.Log(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -117,19 +123,14 @@ public class IdentityService
|
|||
var issuedAt = DateTimeOffset.FromUnixTimeSeconds(iat).DateTime;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
UserCache = user;
|
||||
return UserCache;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warn("Error loading user");
|
||||
Logger.Warn(e);
|
||||
await ErrorLogService.Log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Repositories.Subscriptions;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
@ -14,18 +16,21 @@ public class SubscriptionService
|
|||
private readonly IdentityService IdentityService;
|
||||
private readonly ConfigService ConfigService;
|
||||
private readonly OneTimeJwtService OneTimeJwtService;
|
||||
private readonly AuditLogService AuditLogService;
|
||||
|
||||
public SubscriptionService(SubscriptionRepository subscriptionRepository,
|
||||
UserRepository userRepository,
|
||||
IdentityService identityService,
|
||||
ConfigService configService,
|
||||
OneTimeJwtService oneTimeJwtService)
|
||||
OneTimeJwtService oneTimeJwtService,
|
||||
AuditLogService auditLogService)
|
||||
{
|
||||
SubscriptionRepository = subscriptionRepository;
|
||||
UserRepository = userRepository;
|
||||
IdentityService = identityService;
|
||||
ConfigService = configService;
|
||||
OneTimeJwtService = oneTimeJwtService;
|
||||
AuditLogService = auditLogService;
|
||||
}
|
||||
|
||||
public async Task<Subscription?> Get()
|
||||
|
@ -50,6 +55,8 @@ public class SubscriptionService
|
|||
var user = await IdentityService.Get();
|
||||
user!.Subscription = null;
|
||||
UserRepository.Update(user!);
|
||||
|
||||
await AuditLogService.Log(AuditLogType.CancelSubscription, new[] { user.Email });
|
||||
}
|
||||
public Task<Subscription[]> GetAvailable()
|
||||
{
|
||||
|
@ -91,7 +98,7 @@ public class SubscriptionService
|
|||
public async Task ApplyCode(string code)
|
||||
{
|
||||
var user = (await IdentityService.Get())!;
|
||||
var values = OneTimeJwtService.Validate(code);
|
||||
var values = await OneTimeJwtService.Validate(code);
|
||||
|
||||
if (values == null)
|
||||
throw new DisplayException("Invalid subscription code");
|
||||
|
@ -114,6 +121,8 @@ public class SubscriptionService
|
|||
|
||||
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 OtpNet;
|
||||
|
||||
|
@ -8,11 +10,16 @@ public class TotpService
|
|||
{
|
||||
private readonly IdentityService IdentityService;
|
||||
private readonly UserRepository UserRepository;
|
||||
private readonly AuditLogService AuditLogService;
|
||||
|
||||
public TotpService(IdentityService identityService, UserRepository userRepository)
|
||||
public TotpService(
|
||||
IdentityService identityService,
|
||||
UserRepository userRepository,
|
||||
AuditLogService auditLogService)
|
||||
{
|
||||
IdentityService = identityService;
|
||||
UserRepository = userRepository;
|
||||
AuditLogService = auditLogService;
|
||||
}
|
||||
|
||||
public Task<bool> Verify(string secret, string code)
|
||||
|
@ -38,21 +45,25 @@ public class TotpService
|
|||
|
||||
public async Task Enable()
|
||||
{
|
||||
var user = await IdentityService.Get();
|
||||
var user = (await IdentityService.Get())!;
|
||||
|
||||
user.TotpEnabled = true;
|
||||
user.TotpSecret = GenerateSecret();
|
||||
|
||||
UserRepository.Update(user);
|
||||
|
||||
await AuditLogService.Log(AuditLogType.EnableTotp, user.Email);
|
||||
}
|
||||
|
||||
public async Task Disable()
|
||||
{
|
||||
var user = await IdentityService.Get();
|
||||
var user = (await IdentityService.Get())!;
|
||||
|
||||
user.TotpEnabled = false;
|
||||
|
||||
UserRepository.Update(user);
|
||||
|
||||
await AuditLogService.Log(AuditLogType.DisableTotp, user.Email);
|
||||
}
|
||||
|
||||
private string GenerateSecret()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using JWT.Algorithms;
|
||||
using JWT.Builder;
|
||||
using Logging.Net;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Models.Misc;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
||||
|
@ -12,20 +12,24 @@ public class UserService
|
|||
{
|
||||
private readonly UserRepository UserRepository;
|
||||
private readonly TotpService TotpService;
|
||||
private readonly ConfigService ConfigService;
|
||||
private readonly SecurityLogService SecurityLogService;
|
||||
private readonly AuditLogService AuditLogService;
|
||||
|
||||
private readonly string JwtSecret;
|
||||
|
||||
public UserService(
|
||||
UserRepository userRepository,
|
||||
TotpService totpService,
|
||||
ConfigService configService)
|
||||
ConfigService configService,
|
||||
SecurityLogService securityLogService,
|
||||
AuditLogService auditLogService)
|
||||
{
|
||||
UserRepository = userRepository;
|
||||
TotpService = totpService;
|
||||
ConfigService = configService;
|
||||
SecurityLogService = securityLogService;
|
||||
AuditLogService = auditLogService;
|
||||
|
||||
JwtSecret = ConfigService
|
||||
JwtSecret = configService
|
||||
.GetSection("Moonlight")
|
||||
.GetSection("Security")
|
||||
.GetValue<string>("Token");
|
||||
|
@ -67,11 +71,13 @@ public class UserService
|
|||
|
||||
//var mail = new WelcomeMail(user);
|
||||
//await MailService.Send(mail, user);
|
||||
|
||||
await AuditLogService.Log(AuditLogType.Register, user.Email);
|
||||
|
||||
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()
|
||||
.FirstOrDefault(
|
||||
|
@ -80,18 +86,16 @@ public class UserService
|
|||
|
||||
if (user == null)
|
||||
{
|
||||
Logger.Debug("User not found");
|
||||
|
||||
//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");
|
||||
}
|
||||
|
||||
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");;
|
||||
}
|
||||
|
||||
|
@ -111,29 +115,27 @@ public class UserService
|
|||
if (string.IsNullOrEmpty(totpCode))
|
||||
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)
|
||||
{
|
||||
//AuditLogService.Log("login:success", $"{user.Email} has successfully logged in");
|
||||
|
||||
await AuditLogService.Log(AuditLogType.Login, email);
|
||||
return await GenerateToken(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
//AuditLogService.Log("login:fail", $"Invalid totp code: {totpCode}");
|
||||
await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password });
|
||||
throw new DisplayException("2FA code invalid");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//AuditLogService.Log("login:success", $"{user.Email} has successfully logged in");
|
||||
|
||||
await AuditLogService.Log(AuditLogType.Login, email);
|
||||
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.TokenValidTime = DateTime.Now;
|
||||
|
@ -141,26 +143,27 @@ public class UserService
|
|||
|
||||
//var mail = new NewPasswordMail(user);
|
||||
//await MailService.Send(mail, user);
|
||||
|
||||
//AuditLogService.Log("password:change", "The password has been set to a new one");
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
||||
await AuditLogService.Log(AuditLogType.ChangePassword, user.Email);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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))
|
||||
{
|
||||
//TODO: Maybe log
|
||||
return Task.FromResult(user);
|
||||
await AuditLogService.LogSystem(AuditLogType.Login, user.Email);
|
||||
return user;
|
||||
}
|
||||
|
||||
//TODO: Log
|
||||
await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, new[] { id.ToString(), 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.Services;
|
||||
using Moonlight.App.Services.Interop;
|
||||
using Moonlight.App.Services.LogServices;
|
||||
using Moonlight.App.Services.Notifications;
|
||||
using Moonlight.App.Services.OAuth2;
|
||||
using Moonlight.App.Services.Sessions;
|
||||
|
@ -80,7 +81,10 @@ namespace Moonlight
|
|||
builder.Services.AddScoped<GoogleOAuth2Service>();
|
||||
builder.Services.AddScoped<DiscordOAuth2Service>();
|
||||
|
||||
|
||||
// Loggers
|
||||
builder.Services.AddScoped<SecurityLogService>();
|
||||
builder.Services.AddScoped<AuditLogService>();
|
||||
builder.Services.AddScoped<ErrorLogService>();
|
||||
|
||||
// Support
|
||||
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 Moonlight.App.Services.LogServices
|
||||
@using Moonlight.App.Services.Sessions
|
||||
|
||||
@inherits ErrorBoundary
|
||||
|
||||
@inject IdentityService IdentityService
|
||||
@inject ErrorLogService ErrorLogService
|
||||
|
||||
@if (CurrentException is null)
|
||||
{
|
||||
|
@ -52,13 +53,7 @@ else
|
|||
{
|
||||
receivedExceptions.Add(exception);
|
||||
|
||||
var user = await IdentityService.Get();
|
||||
var id = user == null ? -1 : user.Id;
|
||||
|
||||
Logger.Error($"[{id}] An unhanded exception occured:");
|
||||
Logger.Error(exception);
|
||||
|
||||
//TODO: Create error report
|
||||
await ErrorLogService.Log(exception);
|
||||
|
||||
await base.OnErrorAsync(exception);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
{
|
||||
protected override async Task OnErrorAsync(Exception exception)
|
||||
{
|
||||
Logger.Debug(exception);
|
||||
|
||||
if (exception is DisplayException displayException)
|
||||
{
|
||||
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>
|
||||
</div>
|
||||
<div class="menu-item">
|
||||
<a class="menu-link" href="/admin/general">
|
||||
<a class="menu-link" href="/admin/system">
|
||||
<span class="menu-icon">
|
||||
<i class="bx bx-chip"></i>
|
||||
</span>
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
}
|
||||
}
|
||||
</select>
|
||||
<WorkerButton
|
||||
<WButton
|
||||
OnClick="Save"
|
||||
Text="@(TranslationService.Translate("Change"))"
|
||||
WorkingText="@(TranslationService.Translate("Changing"))"
|
||||
CssClasses="btn-primary"></WorkerButton>
|
||||
CssClasses="btn-primary"></WButton>
|
||||
</LazyLoader>
|
||||
</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.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]
|
||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQXV0aFxMb2dpbi5yYXpvcg==
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
@ -67,6 +71,10 @@ build_metadata.AdditionalFiles.CssScope =
|
|||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRm9ybXNcV0J1dHRvbi5yYXpvcg==
|
||||
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]
|
||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcTmF2aWdhdGlvbnNcUHJvZmlsZU5hdmlnYXRpb24ucmF6b3I=
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
@ -227,6 +235,18 @@ build_metadata.AdditionalFiles.CssScope =
|
|||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEFkbWluXFN1cHBvcnRcVmlldy5yYXpvcg==
|
||||
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]
|
||||
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXERvbWFpbnMucmF6b3I=
|
||||
build_metadata.AdditionalFiles.CssScope =
|
||||
|
|
|
@ -257,3 +257,13 @@ Cancel Subscription;Cancel Subscription
|
|||
Active until;Active until
|
||||
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
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue