Added moonlight resources. Optimised moonlight legacy html rendering

This commit is contained in:
Marcel Baumgartner 2023-02-15 21:25:51 +01:00
parent 8c67273d40
commit 764ff894af
117 changed files with 82725 additions and 1207 deletions

1
.gitignore vendored
View file

@ -431,3 +431,4 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
.idea/.idea.Moonlight/.idea/discord.xml

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EfCoreCommonOptions">
<option name="solutionLevelOptions">
<map>
<entry key="migrationsProject" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
<entry key="startupProject" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
</map>
</option>
</component>
</project>

View file

@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database.Entities;
using Moonlight.App.Services;
namespace Moonlight.App.Database;
public class DataContext : DbContext
{
private readonly ConfigService ConfigService;
public DataContext(ConfigService configService)
{
ConfigService = configService;
}
public DbSet<DockerImage> DockerImages { get; set; }
public DbSet<Image> Images { get; set; }
public DbSet<ImageTag> ImageTags { get; set; }
public DbSet<ImageVariable> ImageVariables { get; set; }
public DbSet<Node> Nodes { get; set; }
public DbSet<NodeAllocation> NodeAllocations { get; set; }
public DbSet<Server> Servers { get; set; }
public DbSet<ServerBackup> ServerBackups { get; set; }
public DbSet<ServerVariable> ServerVariables { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<LoadingMessage> LoadingMessages { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var config = ConfigService
.GetSection("Moonlight")
.GetSection("Database");
var connectionString = $"host={config.GetValue<string>("Host")};" +
$"port={config.GetValue<int>("Port")};" +
$"database={config.GetValue<string>("Database")};" +
$"uid={config.GetValue<string>("Username")};" +
$"pwd={config.GetValue<string>("Password")}";
optionsBuilder.UseMySql(
connectionString,
ServerVersion.Parse("5.7.37-mysql"),
builder =>
{
builder.EnableRetryOnFailure(5);
}
);
}
}
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class DockerImage
{
public int Id { get; set; }
public bool Default { get; set; } = false;
public string Name { get; set; } = "";
}

View file

@ -0,0 +1,20 @@
namespace Moonlight.App.Database.Entities;
public class Image
{
public int Id { get; set; }
public Guid Uuid { get; set; }
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public string ConfigFiles { get; set; } = "{}";
public string StopCommand { get; set; } = "";
public string StartupDetection { get; set; } = "";
public string InstallScript { get; set; } = "";
public string InstallDockerImage { get; set; } = "";
public string InstallEntrypoint { get; set; } = "";
public string Startup { get; set; } = "";
public List<DockerImage> DockerImages { get; set; } = new();
public List<ImageVariable> Variables { get; set; } = new();
public List<ImageTag> Tags { get; set; } = new();
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class ImageTag
{
public int Id { get; set; }
public string Name { get; set; } = "";
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class ImageVariable
{
public int Id { get; set; }
public string Key { get; set; } = "";
public string DefaultValue { get; set; } = "";
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class LoadingMessage
{
public int Id { get; set; }
public string Message { get; set; } = "";
}

View file

@ -0,0 +1,14 @@
namespace Moonlight.App.Database.Entities;
public class Node
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Fqdn { get; set; } = "";
public string TokenId { get; set; } = "";
public string Token { get; set; } = "";
public int SftpPort { get; set; }
public int HttpPort { get; set; }
public int MoonlightDaemonPort { get; set; }
public List<NodeAllocation> Allocations { get; set; } = new();
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class NodeAllocation
{
public int Id { get; set; }
public int Port { get; set; }
}

View file

@ -0,0 +1,23 @@
namespace Moonlight.App.Database.Entities;
public class Server
{
public int Id { get; set; }
public Guid Uuid { get; set; }
public string Name { get; set; } = "";
public int Cpu { get; set; }
public long Memory { get; set; }
public long Disk { get; set; }
public Image Image { get; set; } = null!;
public int DockerImageIndex { get; set; } = 0;
public string OverrideStartup { get; set; } = "";
public bool Installing { get; set; } = false;
public bool Suspended { get; set; } = false;
public List<ServerVariable> Variables { get; set; } = new();
public List<ServerBackup> Backups { get; set; } = new();
public List<NodeAllocation> Allocations { get; set; } = new();
public NodeAllocation MainAllocation { get; set; } = null!;
public Node Node { get; set; } = null!;
public User Owner { get; set; } = null!;
}

View file

@ -0,0 +1,11 @@
namespace Moonlight.App.Database.Entities;
public class ServerBackup
{
public int Id { get; set; }
public string Name { get; set; } = "";
public Guid Uuid { get; set; }
public DateTime CreatedAt { get; set; }
public bool Created { get; set; } = false;
public long Bytes { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class ServerVariable
{
public int Id { get; set; }
public string Key { get; set; } = "";
public string Value { get; set; } = "";
}

View file

@ -0,0 +1,26 @@
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities;
public class User
{
public int Id { get; set; }
public string FirstName { get; set; } = "";
public string LastName { get; set; } = "";
public string Email { get; set; } = "";
public string Password { get; set; } = "";
public string Address { get; set; } = "";
public string City { get; set; } = "";
public string State { get; set; } = "";
public string Country { get; set; } = "";
public UserStatus Status { get; set; } = UserStatus.Unverified;
public bool TotpEnabled { get; set; }
public string TotpSecret { get; set; } = "";
public DateTime TokenValidTime { get; set; } = DateTime.Now;
public long DiscordId { get; set; }
public string DiscordUsername { get; set; } = "";
public string DiscordDiscriminator { get; set; } = "";
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public bool Admin { get; set; }
}

View file

@ -0,0 +1,515 @@
// <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("20230215200722_InitialCreate")]
partial class InitialCreate
{
/// <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.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.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.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<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.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.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<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.ToTable("Users");
});
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.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.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.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");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,434 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.App.Database.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Images",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Uuid = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ConfigFiles = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
StopCommand = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
StartupDetection = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
InstallScript = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
InstallDockerImage = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
InstallEntrypoint = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Startup = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_Images", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "LoadingMessages",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Message = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_LoadingMessages", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Nodes",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Fqdn = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TokenId = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Token = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
SftpPort = table.Column<int>(type: "int", nullable: false),
HttpPort = table.Column<int>(type: "int", nullable: false),
MoonlightDaemonPort = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Nodes", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
FirstName = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
LastName = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Email = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Password = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Address = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
City = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
State = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Country = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Status = table.Column<int>(type: "int", nullable: false),
TotpEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
TotpSecret = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TokenValidTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
DiscordId = table.Column<long>(type: "bigint", nullable: false),
DiscordUsername = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DiscordDiscriminator = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
Admin = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "DockerImages",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Default = table.Column<bool>(type: "tinyint(1)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ImageId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_DockerImages", x => x.Id);
table.ForeignKey(
name: "FK_DockerImages_Images_ImageId",
column: x => x.ImageId,
principalTable: "Images",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ImageTags",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ImageId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ImageTags", x => x.Id);
table.ForeignKey(
name: "FK_ImageTags_Images_ImageId",
column: x => x.ImageId,
principalTable: "Images",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ImageVariables",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Key = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DefaultValue = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ImageId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ImageVariables", x => x.Id);
table.ForeignKey(
name: "FK_ImageVariables_Images_ImageId",
column: x => x.ImageId,
principalTable: "Images",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "NodeAllocations",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Port = table.Column<int>(type: "int", nullable: false),
NodeId = table.Column<int>(type: "int", nullable: true),
ServerId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_NodeAllocations", x => x.Id);
table.ForeignKey(
name: "FK_NodeAllocations_Nodes_NodeId",
column: x => x.NodeId,
principalTable: "Nodes",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Servers",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Uuid = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Cpu = table.Column<int>(type: "int", nullable: false),
Memory = table.Column<long>(type: "bigint", nullable: false),
Disk = table.Column<long>(type: "bigint", nullable: false),
ImageId = table.Column<int>(type: "int", nullable: false),
DockerImageIndex = table.Column<int>(type: "int", nullable: false),
OverrideStartup = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Installing = table.Column<bool>(type: "tinyint(1)", nullable: false),
Suspended = table.Column<bool>(type: "tinyint(1)", nullable: false),
MainAllocationId = table.Column<int>(type: "int", nullable: false),
NodeId = table.Column<int>(type: "int", nullable: false),
OwnerId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Servers", x => x.Id);
table.ForeignKey(
name: "FK_Servers_Images_ImageId",
column: x => x.ImageId,
principalTable: "Images",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_NodeAllocations_MainAllocationId",
column: x => x.MainAllocationId,
principalTable: "NodeAllocations",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_Nodes_NodeId",
column: x => x.NodeId,
principalTable: "Nodes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_Users_OwnerId",
column: x => x.OwnerId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ServerBackups",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Uuid = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
Created = table.Column<bool>(type: "tinyint(1)", nullable: false),
Bytes = table.Column<long>(type: "bigint", nullable: false),
ServerId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerBackups", x => x.Id);
table.ForeignKey(
name: "FK_ServerBackups_Servers_ServerId",
column: x => x.ServerId,
principalTable: "Servers",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "ServerVariables",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Key = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Value = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ServerId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerVariables", x => x.Id);
table.ForeignKey(
name: "FK_ServerVariables_Servers_ServerId",
column: x => x.ServerId,
principalTable: "Servers",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_DockerImages_ImageId",
table: "DockerImages",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_ImageTags_ImageId",
table: "ImageTags",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_ImageVariables_ImageId",
table: "ImageVariables",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_NodeAllocations_NodeId",
table: "NodeAllocations",
column: "NodeId");
migrationBuilder.CreateIndex(
name: "IX_NodeAllocations_ServerId",
table: "NodeAllocations",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_ServerBackups_ServerId",
table: "ServerBackups",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_Servers_ImageId",
table: "Servers",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_Servers_MainAllocationId",
table: "Servers",
column: "MainAllocationId");
migrationBuilder.CreateIndex(
name: "IX_Servers_NodeId",
table: "Servers",
column: "NodeId");
migrationBuilder.CreateIndex(
name: "IX_Servers_OwnerId",
table: "Servers",
column: "OwnerId");
migrationBuilder.CreateIndex(
name: "IX_ServerVariables_ServerId",
table: "ServerVariables",
column: "ServerId");
migrationBuilder.AddForeignKey(
name: "FK_NodeAllocations_Servers_ServerId",
table: "NodeAllocations",
column: "ServerId",
principalTable: "Servers",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Servers_Images_ImageId",
table: "Servers");
migrationBuilder.DropForeignKey(
name: "FK_NodeAllocations_Nodes_NodeId",
table: "NodeAllocations");
migrationBuilder.DropForeignKey(
name: "FK_Servers_Nodes_NodeId",
table: "Servers");
migrationBuilder.DropForeignKey(
name: "FK_NodeAllocations_Servers_ServerId",
table: "NodeAllocations");
migrationBuilder.DropTable(
name: "DockerImages");
migrationBuilder.DropTable(
name: "ImageTags");
migrationBuilder.DropTable(
name: "ImageVariables");
migrationBuilder.DropTable(
name: "LoadingMessages");
migrationBuilder.DropTable(
name: "ServerBackups");
migrationBuilder.DropTable(
name: "ServerVariables");
migrationBuilder.DropTable(
name: "Images");
migrationBuilder.DropTable(
name: "Nodes");
migrationBuilder.DropTable(
name: "Servers");
migrationBuilder.DropTable(
name: "NodeAllocations");
migrationBuilder.DropTable(
name: "Users");
}
}
}

View file

@ -0,0 +1,512 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.App.Database;
#nullable disable
namespace Moonlight.App.Database.Migrations
{
[DbContext(typeof(DataContext))]
partial class DataContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
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.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.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<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.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.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<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.ToTable("Users");
});
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.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.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.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");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,58 @@
using Logging.Net;
using Newtonsoft.Json;
namespace Moonlight.App.Helpers
{
public class TranslationHelper
{
private readonly Dictionary<string, IConfiguration> Languages;
public TranslationHelper()
{
Languages = new();
foreach (var file in Directory.GetFiles("resources/lang"))
{
var langKey = Path.GetFileName(file)
.Replace(Path.GetExtension(file), "");
Languages.Add(langKey, new ConfigurationBuilder()
.AddJsonFile(file)
.Build());
}
}
public string? Get(string langKey, string key)
{
if (Languages.ContainsKey(langKey))
{
var parts = key.Split(".");
IConfigurationSection? section = null;
foreach (var part in parts)
{
if (part == parts.Last())
{
if (section == null)
return Languages[langKey].GetValue<string>(part);
else
return section.GetValue<string>(part);
}
else
{
if (section == null)
section = Languages[langKey].GetSection(part);
else
section = section.GetSection(part);
}
}
return key;
}
else
{
return "Invalid lang key";
}
}
}
}

View file

@ -0,0 +1,48 @@
using Newtonsoft.Json;
namespace Moonlight.App.Models.IpLocate.Resources;
public class IpLocate
{
[JsonProperty("query")]
public string Query { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("countryCode")]
public string CountryCode { get; set; }
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("regionName")]
public string RegionName { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("zip")]
public string Zip { get; set; }
[JsonProperty("lat")]
public double Lat { get; set; }
[JsonProperty("lon")]
public double Lon { get; set; }
[JsonProperty("timezone")]
public string Timezone { get; set; }
[JsonProperty("isp")]
public string Isp { get; set; }
[JsonProperty("org")]
public string Org { get; set; }
[JsonProperty("as")]
public string As { get; set; }
}

View file

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Components;
using Moonlight.App.Services.Interop;
namespace Moonlight.App.Models.Misc;
public class Session
{
public string Ip { get; set; }
public string Url { get; set; }
public string Device { get; set; }
public int UserId { get; set; }
public DateTime CreatedAt { get; set; }
public NavigationManager Navigation { get; set; }
public AlertService AlertService { get; set; }
}

View file

@ -0,0 +1,12 @@
namespace Moonlight.App.Models.Misc;
public enum UserStatus
{
Unverified,
Verified,
VerifyPending,
VerifyFailed,
Warned,
Banned,
Disabled
}

View file

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database;
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Repositories;
public class NodeRepository : IDisposable
{
private readonly DataContext DataContext;
public NodeRepository(DataContext dataContext)
{
DataContext = dataContext;
}
public DbSet<Node> Get()
{
return DataContext.Nodes;
}
public Node Add(Node node)
{
var x = DataContext.Nodes.Add(node);
DataContext.SaveChanges();
return x.Entity;
}
public void Update(Node node)
{
DataContext.Nodes.Update(node);
DataContext.SaveChanges();
}
public void Delete(Node node)
{
DataContext.Nodes.Remove(node);
DataContext.SaveChanges();
}
public void Dispose()
{
DataContext.Dispose();
}
}

View file

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database;
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Repositories.Servers;
public class ServerBackupRepository : IDisposable
{
private readonly DataContext DataContext;
public ServerBackupRepository(DataContext dataContext)
{
DataContext = dataContext;
}
public DbSet<ServerBackup> Get()
{
return DataContext.ServerBackups;
}
public ServerBackup Add(ServerBackup serverBackup)
{
var x = DataContext.ServerBackups.Add(serverBackup);
DataContext.SaveChanges();
return x.Entity;
}
public void Update(ServerBackup serverBackup)
{
DataContext.ServerBackups.Update(serverBackup);
DataContext.SaveChanges();
}
public void Delete(ServerBackup serverBackup)
{
DataContext.ServerBackups.Remove(serverBackup);
DataContext.SaveChanges();
}
public void Dispose()
{
DataContext.Dispose();
}
}

View file

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database;
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Repositories.Servers;
public class ServerRepository : IDisposable
{
private readonly DataContext DataContext;
public ServerRepository(DataContext dataContext)
{
DataContext = dataContext;
}
public DbSet<Server> Get()
{
return DataContext.Servers;
}
public Server Add(Server server)
{
var x = DataContext.Servers.Add(server);
DataContext.SaveChanges();
return x.Entity;
}
public void Update(Server server)
{
DataContext.Servers.Update(server);
DataContext.SaveChanges();
}
public void Delete(Server server)
{
DataContext.Servers.Remove(server);
DataContext.SaveChanges();
}
public void Dispose()
{
DataContext.Dispose();
}
}

View file

@ -0,0 +1,37 @@
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Repositories;
public class SessionRepository
{
private readonly List<Session> Sessions;
public SessionRepository()
{
Sessions = new();
}
public Session[] Get()
{
lock (Sessions)
{
return Sessions.ToArray();
}
}
public void Add(Session session)
{
lock (Sessions)
{
Sessions.Add(session);
}
}
public void Delete(Session session)
{
lock (Sessions)
{
Sessions.Remove(session);
}
}
}

View file

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database;
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Repositories;
public class UserRepository : IDisposable
{
private readonly DataContext DataContext;
public UserRepository(DataContext dataContext)
{
DataContext = dataContext;
}
public DbSet<User> Get()
{
return DataContext.Users;
}
public User Add(User user)
{
var x = DataContext.Users.Add(user);
DataContext.SaveChanges();
return x.Entity;
}
public void Update(User user)
{
DataContext.Users.Update(user);
DataContext.SaveChanges();
}
public void Delete(User user)
{
DataContext.Users.Remove(user);
DataContext.SaveChanges();
}
public void Dispose()
{
DataContext.Dispose();
}
}

View file

@ -0,0 +1,46 @@
using System.Text;
using Logging.Net;
using Microsoft.Extensions.Primitives;
namespace Moonlight.App.Services;
public class ConfigService : IConfiguration
{
private IConfiguration Configuration;
public bool DebugMode { get; private set; } = false;
public ConfigService()
{
Configuration = new ConfigurationBuilder().AddJsonStream(
new MemoryStream(Encoding.ASCII.GetBytes(File.ReadAllText("..\\..\\appsettings.json")))
).Build();
// Env vars
var debugVar = Environment.GetEnvironmentVariable("ML_DEBUG");
if (debugVar != null)
DebugMode = bool.Parse(debugVar);
}
public IEnumerable<IConfigurationSection> GetChildren()
{
return Configuration.GetChildren();
}
public IChangeToken GetReloadToken()
{
return Configuration.GetReloadToken();
}
public IConfigurationSection GetSection(string key)
{
return Configuration.GetSection(key);
}
public string this[string key]
{
get => Configuration[key];
set => Configuration[key] = value;
}
}

View file

@ -0,0 +1,82 @@
using CurrieTechnologies.Razor.SweetAlert2;
namespace Moonlight.App.Services.Interop;
public class AlertService
{
private readonly SweetAlertService SweetAlertService;
public AlertService(SweetAlertService service)
{
SweetAlertService = service;
}
public async Task Info(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
Icon = SweetAlertIcon.Info
});
}
public async Task Success(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
Icon = SweetAlertIcon.Success
});
}
public async Task Warning(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
Icon = SweetAlertIcon.Warning
});
}
public async Task Error(string title, string desciption)
{
await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
Icon = SweetAlertIcon.Error
});
}
public async Task<bool> YesNo(string title, string desciption, string yesText, string noText)
{
var result = await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
ShowCancelButton = false,
ShowDenyButton = true,
ShowConfirmButton = true,
ConfirmButtonText = yesText,
DenyButtonText = noText
});
return result.IsConfirmed;
}
public async Task<string> Text(string title, string desciption, string setValue)
{
var result = await SweetAlertService.FireAsync(new SweetAlertOptions()
{
Title = title,
Text = desciption,
Input = SweetAlertInputType.Text,
InputValue = setValue
});
return result.Value;
}
}

View file

@ -0,0 +1,18 @@
using Microsoft.JSInterop;
namespace Moonlight.App.Services.Interop;
public class ClipboardService
{
private readonly IJSRuntime JsRuntime;
public ClipboardService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task CopyToClipboard(string data)
{
await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data);
}
}

View file

@ -0,0 +1,33 @@
using Microsoft.JSInterop;
namespace Moonlight.App.Services.Interop;
public class ToastService
{
private readonly IJSRuntime JsRuntime;
public ToastService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task Info(string message)
{
await JsRuntime.InvokeVoidAsync("showInfoToast", message);
}
public async Task Error(string message)
{
await JsRuntime.InvokeVoidAsync("showErrorToast", message);
}
public async Task Warning(string message)
{
await JsRuntime.InvokeVoidAsync("showWarningToast", message);
}
public async Task Success(string message)
{
await JsRuntime.InvokeVoidAsync("showSuccessToast", message);
}
}

View file

@ -0,0 +1,51 @@
using Microsoft.JSInterop;
namespace Moonlight.App.Services.Sessions;
public class CookieService
{
private readonly IJSRuntime JsRuntime;
private string Expires = "";
public CookieService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
ExpireDays = 300;
}
public async Task SetValue(string key, string value, int? days = null)
{
var curExp = (days != null) ? (days > 0 ? DateToUTC(days.Value) : "") : Expires;
await SetCookie($"{key}={value}; expires={curExp}; path=/");
}
public async Task<string> GetValue(string key, string def = "")
{
var cValue = await GetCookie();
if (string.IsNullOrEmpty(cValue)) return def;
var vals = cValue.Split(';');
foreach (var val in vals)
if(!string.IsNullOrEmpty(val) && val.IndexOf('=') > 0)
if(val.Substring(1, val.IndexOf('=') - 1).Trim().Equals(key, StringComparison.OrdinalIgnoreCase))
return val.Substring(val.IndexOf('=') + 1);
return def;
}
private async Task SetCookie(string value)
{
await JsRuntime.InvokeVoidAsync("eval", $"document.cookie = \"{value}\"");
}
private async Task<string> GetCookie()
{
return await JsRuntime.InvokeAsync<string>("eval", $"document.cookie");
}
private int ExpireDays
{
set => Expires = DateToUTC(value);
}
private static string DateToUTC(int days) => DateTime.Now.AddDays(days).ToUniversalTime().ToString("R");
}

View file

@ -0,0 +1,167 @@
using System.Text;
using JWT.Algorithms;
using JWT.Builder;
using JWT.Exceptions;
using Logging.Net;
using Moonlight.App.Database.Entities;
using Moonlight.App.Repositories;
using UAParser;
namespace Moonlight.App.Services.Sessions;
public class IdentityService
{
private readonly UserRepository UserRepository;
private readonly CookieService CookieService;
private readonly IHttpContextAccessor HttpContextAccessor;
private readonly string Secret;
private User? UserCache;
public IdentityService(
CookieService cookieService,
UserRepository userRepository,
IHttpContextAccessor httpContextAccessor,
ConfigService configService)
{
CookieService = cookieService;
UserRepository = userRepository;
HttpContextAccessor = httpContextAccessor;
Secret = configService
.GetSection("Moonlight")
.GetSection("Security")
.GetValue<string>("Token");
}
public async Task<User?> Get()
{
try
{
if (UserCache != null)
return UserCache;
var token = "none";
// Load token via http context if available
if (HttpContextAccessor.HttpContext != null)
{
var request = HttpContextAccessor.HttpContext.Request;
if (request.Cookies.ContainsKey("token"))
{
token = request.Cookies["token"];
}
}
else // if not we check the cookies manually via js. this may not often work
{
token = await CookieService.GetValue("token", "none");
}
if (token == "none")
{
return null;
}
if (string.IsNullOrEmpty(token))
return null;
var json = "";
try
{
json = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSecret(Secret)
.Decode(token);
}
catch (TokenExpiredException)
{
return null;
}
catch (SignatureVerificationException)
{
//TODO: Heavy warn and write it to the logs
Logger.Warn("Someone tried to modify his data: " + token);
return null;
}
catch (Exception e)
{
Logger.Warn("Error parsing and validating token");
Logger.Warn(e);
return null;
}
// To make it easier to use the json data
var data = new ConfigurationBuilder().AddJsonStream(
new MemoryStream(Encoding.ASCII.GetBytes(json))
).Build();
var userid = data.GetValue<int>("userid");
var user = UserRepository.Get().FirstOrDefault(y => y.Id == userid);
if (user == null)
{
Logger.Warn($"Cannot find user with the id '{userid}' in the database. Maybe the user has been deleted or a token has been successfully faked by a hacker");
return null;
}
var iat = data.GetValue<long>("iat", -1);
if (iat == -1)
{
Logger.Debug("Legacy token found (without the time the token has been issued at)");
return null;
}
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);
return null;
}
}
public 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();
}
public string GetDevice()
{
if (HttpContextAccessor.HttpContext == null)
return "N/A";
try
{
var uaParser = Parser.GetDefault();
var info = uaParser.Parse(HttpContextAccessor.HttpContext.Request.Headers.UserAgent);
return $"{info.OS} - {info.Device}";
}
catch (Exception e)
{
return "UserAgent not present";
}
}
}

View file

@ -0,0 +1,37 @@
using System.Net;
using Moonlight.App.Models.IpLocate.Resources;
using Newtonsoft.Json;
namespace Moonlight.App.Services.Sessions;
public class IpLocateService
{
private readonly IdentityService IdentityService;
public IpLocateService(IdentityService identityService)
{
IdentityService = identityService;
}
public async Task<string> GetLocation()
{
var ip = IdentityService.GetIp();
var location = "N/A";
if (ip != "N/A")
{
using (var wc = new WebClient())
{
var res = JsonConvert.DeserializeObject<IpLocate>(
await wc.DownloadStringTaskAsync(
$"http://ip-api.com/json/{ip}"
)
);
location = $"{res.Country} - {res.RegionName} - {res.City} ({res.Org})";
}
}
return location;
}
}

View file

@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Components;
using Moonlight.App.Database.Entities;
using Moonlight.App.Models.Misc;
using Moonlight.App.Repositories;
using Moonlight.App.Services.Interop;
namespace Moonlight.App.Services.Sessions;
public class SessionService
{
private readonly SessionRepository SessionRepository;
private readonly IdentityService IdentityService;
private readonly NavigationManager NavigationManager;
private readonly AlertService AlertService;
private Session OwnSession;
public SessionService(
SessionRepository sessionRepository,
IdentityService identityService,
NavigationManager navigationManager,
AlertService alertService)
{
SessionRepository = sessionRepository;
IdentityService = identityService;
NavigationManager = navigationManager;
AlertService = alertService;
}
public async Task Register()
{
var user = await IdentityService.Get();
var userId = -1;
if (user != null)
userId = user.Id;
OwnSession = new Session()
{
Ip = IdentityService.GetIp(),
Url = NavigationManager.Uri,
Device = IdentityService.GetDevice(),
CreatedAt = DateTime.Now,
UserId = userId,
Navigation = NavigationManager,
AlertService = AlertService
};
SessionRepository.Add(OwnSession);
}
public void Refresh()
{
OwnSession.Url = NavigationManager.Uri;
}
public void Close()
{
SessionRepository.Delete(OwnSession);
}
public Session[] GetAll()
{
return SessionRepository.Get();
}
public void ReloadUserSessions(User user)
{
foreach (var session in SessionRepository.Get())
{
if (session.UserId == user.Id)
{
session.Navigation.NavigateTo(session.Navigation.Uri, true);
}
}
}
}

View file

@ -0,0 +1,98 @@
using Microsoft.AspNetCore.Components;
using Moonlight.App.Helpers;
namespace Moonlight.App.Services
{
public class TranslationService
{
private string LanguageCode { get; set; } = "en_us";
private readonly string FallbackLanguage = "en_us";
private TranslationHelper Helper { get; }
private HttpContext HttpContext { get; }
public TranslationService(TranslationHelper helper, IHttpContextAccessor httpContextAccessor)
{
Helper = helper;
HttpContext = httpContextAccessor.HttpContext!;
LanguageCode = FallbackLanguage;
try
{
var langHeader = HttpContext.Request.Headers["Accept-Language"].ToString();
var important = langHeader.Split(";").First().ToLower().Split(",");
foreach (var v in important)
{
if (v.Contains("de"))
{
LanguageCode = "de_de";
break;
}
else if (v.Contains("en"))
{
LanguageCode = "en_us";
break;
}
}
var cookies = HttpContext.Request.Headers["Cookie"].ToString().Split(new string[] { ",", ";" }, StringSplitOptions.TrimEntries);
foreach (var cookie in cookies)
{
var name = cookie.Split("=").First().Trim();
var value = cookie.Split("=").Last().Trim();
if (name == "lang")
{
if (value.Contains("de"))
{
LanguageCode = "de_de";
break;
}
else if (value.Contains("en"))
{
LanguageCode = "en_us";
break;
}
}
}
}
catch (Exception)
{
}
}
public string Translate(string key, params object[] parameters)
{
try
{
var text = Helper.Get(LanguageCode, key);
if (text == null)
return key;
int i = 0;
foreach (var param in parameters)
{
text = text.Replace($"{{{i}}}", param.ToString());
i++;
}
return text;
}
catch (Exception ex)
{
Logging.Net.Logger.Error(ex);
return key;
}
}
public MarkupString TranslateMarkup(string key, params object[] parameters)
{
return new MarkupString(Translate(key, parameters));
}
}
}

View file

@ -1,4 +1,6 @@
<Router AppAssembly="@typeof(App).Assembly">
@using Moonlight.Shared.Layouts
<Router AppAssembly="@typeof(BlazorApp).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />

View file

@ -1,13 +0,0 @@
namespace Moonlight.Data
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View file

@ -1,20 +0,0 @@
namespace Moonlight.Data
{
public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
}).ToArray());
}
}
}

View file

@ -9,7 +9,56 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="aaPanelSharp" Version="1.0.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<PackageReference Include="Blazor.ContextMenu" Version="1.15.0" />
<PackageReference Include="BlazorMonaco" Version="3.0.0" />
<PackageReference Include="BlazorTable" Version="1.17.0" />
<PackageReference Include="CurrieTechnologies.Razor.SweetAlert2" Version="5.4.0" />
<PackageReference Include="Discord.Net" Version="3.9.0" />
<PackageReference Include="GravatarSharp.Core" Version="0.9.0.2" />
<PackageReference Include="JWT" Version="10.0.2" />
<PackageReference Include="Logging.Net" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
<PackageReference Include="MineStat" Version="3.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3-beta1" />
<PackageReference Include="Otp.NET" Version="1.3.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0" />
<PackageReference Include="PteroConsole.NET" Version="1.0.4" />
<PackageReference Include="QRCoder" Version="1.4.3" />
<PackageReference Include="RestSharp" Version="109.0.0-preview.1" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="XtermBlazor" Version="1.6.1" />
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="wwwroot\css\bootstrap\bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\css\bootstrap\bootstrap.min.css.map" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\FONT-LICENSE" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\css\open-iconic-bootstrap.min.css" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\fonts\open-iconic.eot" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\fonts\open-iconic.otf" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\fonts\open-iconic.svg" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\fonts\open-iconic.ttf" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\font\fonts\open-iconic.woff" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\ICON-LICENSE" />
<_ContentIncludedByDefault Remove="wwwroot\css\open-iconic\README.md" />
<_ContentIncludedByDefault Remove="wwwroot\css\site.css" />
</ItemGroup>
<ItemGroup>
<Folder Include="App\Database\Migrations" />
<Folder Include="App\Exceptions" />
<Folder Include="App\Http\Controllers" />
<Folder Include="App\Http\Middleware" />
<Folder Include="App\Http\Requests" />
<Folder Include="App\Http\Resources" />
<Folder Include="wwwroot\assets\media" />
</ItemGroup>
</Project>

View file

@ -1,18 +0,0 @@
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View file

@ -1,48 +0,0 @@
@page "/fetchdata"
<PageTitle>Weather forecast</PageTitle>
@using Moonlight.Data
@inject WeatherForecastService ForecastService
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}

View file

@ -1,9 +0,0 @@
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />

View file

@ -5,4 +5,25 @@
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
<component type="typeof(BlazorApp)" render-mode="ServerPrerendered" />
<div id="components-reconnect-modal" class="my-reconnect-modal components-reconnect-hide">
<div class="show">
<p>
<br/>
Connecting to moonlight servers
</p>
</div>
<div class="failed">
<p>
<br />
Connection to moonlight servers failed
</p>
</div>
<div class="rejected">
<p>
<br />
Connection to moonlight servers rejected
</p>
</div>
</div>

View file

@ -1,32 +1,111 @@
@using Microsoft.AspNetCore.Components.Web
@using Moonlight.App.Services
@namespace Moonlight.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@inject ConfigService ConfigService
@{
var headerConfig = ConfigService
.GetSection("Moonlight")
.GetSection("Html")
.GetSection("Headers");
var moonlightConfig = ConfigService
.GetSection("Moonlight");
}
<!DOCTYPE html>
<html lang="en">
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
<link href="Moonlight.styles.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
<meta charset="utf-8"/>
<meta property="og:locale" content="de_DE"/>
<meta property="og:type" content="article"/>
<meta content="@(headerConfig.GetValue<string>("Title"))" property="og:title"/>
<meta content="@(headerConfig.GetValue<string>("Description"))" property="og:description"/>
<meta content="@(moonlightConfig.GetValue<string>("AppUrl"))" property="og:url"/>
<meta content="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logofull.png" property="og:image"/>
<meta content="@(headerConfig.GetValue<string>("Color"))" data-react-helmet="true" name="theme-color"/>
<meta content="@(headerConfig.GetValue<string>("Description"))" name="description"/>
<meta content="@(headerConfig.GetValue<string>("Keywords"))" name="keywords"/>
<link rel="shortcut icon" href="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logo.svg"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700"/>
<link rel="stylesheet" type="text/css" href="/assets/css/style.bundle.css"/>
<link rel="stylesheet" type="text/css" href="/assets/css/flashbang.css"/>
<link rel="stylesheet" type="text/css" href="/assets/css/snow.css"/>
<link rel="stylesheet" type="text/css" href="/assets/css/invisiblea.css"/>
<link rel="stylesheet" type="text/css" href="/assets/css/boxicons.min.css"/>
<link rel="stylesheet" type="text/css" href="/assets/css/blazor.css"/>
<link rel="stylesheet" type="text/css" href="/_content/XtermBlazor/XtermBlazor.css"/>
<link rel="stylesheet" type="text/css" href="/_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.css"/>
<link rel="stylesheet" type="text/css" href="/_content/Blazor.ContextMenu/blazorContextMenu.min.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<base href="~/"/>
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>
<title>Loading</title>
</head>
<body>
@RenderBody()
<body
class="app-default"
cz-shortcut-listen="true"
data-kt-app-layout="dark-sidebar"
data-kt-app-header-fixed="true"
data-kt-app-sidebar-fixed="true"
data-kt-app-sidebar-hoverable="true"
data-kt-app-sidebar-push-header="true"
data-kt-app-sidebar-push-toolbar="true"
data-kt-app-sidebar-push-footer="true"
data-kt-app-toolbar-enabled="true">
<div id="blazor-error-ui">
<environment include="Staging,Production">
An error has occurred. This application may no longer respond until reloaded.
</environment>
<environment include="Development">
An unhandled exception has occurred. See browser dev tools for details.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
@RenderBody()
<div id="flashbang" class="flashbanglight"></div>
<div class="app-page-loader flex-column">
<img alt="Logo" src="/api/moonlight/resources/images/logo.svg" class="h-25px"/>
<div class="d-flex align-items-center mt-5">
<span class="spinner-border text-primary" role="status"></span>
<span class="text-muted fs-6 fw-semibold ms-5">CHANGEME</span>
</div>
</div>
<script src="_framework/blazor.server.js"></script>
<script src="/_framework/blazor.server.js"></script>
<script src="/_content/XtermBlazor/XtermBlazor.min.js"></script>
<script src="/_content/BlazorTable/BlazorTable.min.js"></script>
<script src="/_content/BlazorInputFile/inputfile.js"></script>
<script src="/_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
<script src="/_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
<script src="/_content/BlazorMonaco/jsInterop.js"></script>
<script src="/_content/CurrieTechnologies.Razor.SweetAlert2/sweetAlert2.min.js"></script>
<script src="/_content/Blazor-ApexCharts/js/blazor-apex-charts.js"></script>
<script src="/_content/Blazor.ContextMenu/blazorContextMenu.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-search@0.8.2/lib/xterm-addon-search.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-web-links@0.5.0/lib/xterm-addon-web-links.min.js"></script>
<script src="/assets/js/scripts.bundle.js"></script>
<script src="/assets/js/flashbang.js"></script>
<script src="/assets/js/cookieUtils.js"></script>
<script src="/assets/js/clipboard.js"></script>
<script src="/assets/js/toastUtils.js"></script>
<script src="/assets/js/alertUtils.js"></script>
<script src="/assets/js/utils.js"></script>
<script src="/assets/js/loggingUtils.js"></script>
<script src="/assets/js/snow.js"></script>
<script src="/assets/js/recaptcha.js"></script>
<script src="/assets/js/xtermAddons.js"></script>
<script src="/assets/js/monaco.js"></script>
</body>
</html>

View file

@ -1,9 +1,14 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using BlazorTable;
using CurrieTechnologies.Razor.SweetAlert2;
using Moonlight.App.Database;
using Moonlight.App.Helpers;
using Moonlight.App.Repositories;
using Moonlight.App.Repositories.Servers;
using Moonlight.App.Services;
using Moonlight.App.Services.Interop;
using Moonlight.App.Services.Sessions;
using Moonlight.Data;
namespace Company.WebApplication1
namespace Moonlight
{
public class Program
{
@ -14,7 +19,36 @@ namespace Company.WebApplication1
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddHttpContextAccessor();
// Databases
builder.Services.AddDbContext<DataContext>();
// Repositories
builder.Services.AddSingleton<SessionRepository>();
builder.Services.AddScoped<UserRepository>();
builder.Services.AddScoped<NodeRepository>();
builder.Services.AddScoped<ServerRepository>();
builder.Services.AddScoped<ServerBackupRepository>();
// Services
builder.Services.AddScoped<TranslationService>();
builder.Services.AddSingleton<ConfigService>();
builder.Services.AddScoped<CookieService>();
builder.Services.AddScoped<IdentityService>();
builder.Services.AddScoped<IpLocateService>();
builder.Services.AddScoped<SessionService>();
builder.Services.AddScoped<TranslationService>();
builder.Services.AddScoped<AlertService>();
// Helpers
builder.Services.AddSingleton<TranslationHelper>();
// Third party services
builder.Services.AddBlazorTable();
builder.Services.AddSweetAlert2(options => { options.Theme = SweetAlertTheme.Dark; });
builder.Services.AddBlazorContextMenu();
var app = builder.Build();

View file

@ -0,0 +1,21 @@
@using Moonlight.App.Services
@inject TranslationService TranslationService
@inject ConfigService ConfigService
@{
var moonlightConfig = ConfigService
.GetSection("Moonlight");
}
<div class="card card-flush w-lg-650px py-5">
<div class="card-body py-15 py-lg-20">
<div class="mb-14">
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logofull.png" class="h-40px">
</div>
<h1 class="fw-bolder text-gray-900 mb-5">@(TranslationService.Translate("Alerts.Banned.Title"))</h1>
<div class="fw-semibold fs-6 text-gray-500 mb-8">
@(TranslationService.Translate("Alerts.Banned.Details"))
</div>
</div>
</div>

View file

@ -0,0 +1,21 @@
@using Moonlight.App.Services
@inject TranslationService TranslationService
@inject ConfigService ConfigService
@{
var moonlightConfig = ConfigService
.GetSection("Moonlight");
}
<div class="card card-flush w-lg-650px py-5">
<div class="card-body py-15 py-lg-20">
<div class="mb-14">
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logofull.png" class="h-40px">
</div>
<h1 class="fw-bolder text-gray-900 mb-5">@(TranslationService.Translate("Alerts.Disabled.Title"))</h1>
<div class="fw-semibold fs-6 text-gray-500 mb-8">
@(TranslationService.Translate("Alerts.Disabled.Details"))
</div>
</div>
</div>

View file

@ -0,0 +1,73 @@
@using Moonlight.App.Services
@using Logging.Net
@using Moonlight.App.Services.Sessions
@inherits ErrorBoundary
@inject IdentityService IdentityService
@inject TranslationService TranslationService
@if (CurrentException is null)
{
@ChildContent
}
else if (ErrorContent is not null)
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@TranslationService.Translate("Crashes.Component.Title")
</span>
</div>
<div class="text-center">
@TranslationService.Translate("Crashes.Component.Details")
</div>
</div>
</div>
</div>
}
else
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@TranslationService.Translate("Crashes.Component.Title")
</span>
</div>
<div class="text-center">
@TranslationService.Translate("Crashes.Component.Details")
</div>
</div>
</div>
</div>
}
@code
{
List<Exception> receivedExceptions = new();
protected override async Task OnErrorAsync(Exception exception)
{
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 base.OnErrorAsync(exception);
}
public new void Recover()
{
receivedExceptions.Clear();
base.Recover();
}
}

View file

@ -0,0 +1,71 @@
@using Moonlight.App.Services
@using Logging.Net
@using Moonlight.App.Services.Sessions
@inherits ErrorBoundary
@inject IdentityService IdentityService
@inject TranslationService TranslationService
@if (CurrentException is null)
{
@ChildContent
}
else if (ErrorContent is not null)
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@(TranslationService.Translate("Crashes.Global.Title"))
</span>
</div>
<div class="text-center">
@(TranslationService.Translate("Crashes.Global.Details"))
</div>
</div>
</div>
</div>
}
else
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@TranslationService.Translate("Crashes.Global.Title")
</span>
</div>
<div class="text-center">
@TranslationService.Translate("Crashes.Global.Details")
</div>
</div>
</div>
</div>
}
@code
{
List<Exception> receivedExceptions = new();
protected override async Task OnErrorAsync(Exception exception)
{
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);
await base.OnErrorAsync(exception);
}
public new void Recover()
{
receivedExceptions.Clear();
base.Recover();
}
}

View file

@ -0,0 +1,73 @@
@using Logging.Net
@using Moonlight.App.Services
@using Moonlight.App.Services.Sessions
@inherits ErrorBoundary
@inject IdentityService IdentityService
@inject TranslationService TranslationService
@if (CurrentException is null)
{
@ChildContent
}
else if (ErrorContent is not null)
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@TranslationService.Translate("Crashes.Page.Title")
</span>
</div>
<div class="text-center">
@TranslationService.Translate("Crashes.Page.Details")
</div>
</div>
<img class="mx-auto h-150px h-lg-200px" src="/assets/media/svg/illustrations/broken-cable.svg" alt="Broken cable">
</div>
</div>
}
else
{
<div class="card card-flush h-md-100">
<div class="card-body d-flex flex-column justify-content-between mt-9 bgi-no-repeat bgi-size-cover bgi-position-x-center pb-0">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
@TranslationService.Translate("Crashes.Page.Title")
</span>
</div>
<div class="text-center">
@TranslationService.Translate("Crashes.Page.Details")
</div>
</div>
<img class="mx-auto h-150px h-lg-200px" src="/assets/media/svg/illustrations/broken-cable.svg" alt="Broken cable">
</div>
</div>
}
@code
{
List<Exception> receivedExceptions = new();
protected override async Task OnErrorAsync(Exception exception)
{
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);
await base.OnErrorAsync(exception);
}
public new void Recover()
{
receivedExceptions.Clear();
base.Recover();
}
}

View file

@ -0,0 +1,38 @@
@using Moonlight.App.Services
@inject TranslationService TranslationService
@inject ConfigService ConfigService
@{
var marketingConfig = ConfigService
.GetSection("Moonlight")
.GetSection("Marketing");
}
<div id="kt_app_footer" class="app-footer">
<div class="app-container container-fluid d-flex flex-column flex-md-row flex-center flex-md-stack py-3">
<div class="text-dark order-2 order-md-1">
<span class="text-muted fw-semibold me-1">2022 - @DateTime.Now.Year©</span>
<a href="@(marketingConfig.GetValue<string>("Website"))" target="_blank" class="text-gray-800 text-hover-primary">
@(marketingConfig.GetValue<string>("BrandName"))
</a>
</div>
<ul class="menu menu-gray-600 menu-hover-primary fw-semibold order-1">
<li class="menu-item">
<a href="@(marketingConfig.GetValue<string>("About"))" target="_blank" class="menu-link px-2">
@(TranslationService.Translate("Footer.AboutUs"))
</a>
</li>
<li class="menu-item">
<a href="@(marketingConfig.GetValue<string>("Imprint"))" target="_blank" class="menu-link px-2">
@(TranslationService.Translate("Footer.Imprint"))
</a>
</li>
<li class="menu-item">
<a href="@(marketingConfig.GetValue<string>("Privacy"))" target="_blank" class="menu-link px-2">
@(TranslationService.Translate("Footer.Privacy"))
</a>
</li>
</ul>
</div>
</div>

View file

@ -0,0 +1,90 @@
@using Moonlight.App.Helpers
@using Moonlight.App.Repositories
@using Moonlight.App.Services
@using Moonlight.App.Services.Sessions
@using Moonlight.App.Database.Entities
@using Task = System.Threading.Tasks.Task
@inject IdentityService IdentityService
@inject NavigationManager NavigationManager
@inject CookieService CookieService
@inject TranslationService TranslationService
<div class="app-navbar flex-shrink-0">
<div class="app-navbar-item ms-1 ms-lg-3">
<ThemeSwitcher
ToggleBtnClass="btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-35px h-35px w-md-40px h-md-40px"
ToggleBtnIconClass="svg-icon svg-icon-2">
</ThemeSwitcher>
</div>
@if (User != null)
{
<div class="app-navbar-item ms-1 ms-lg-3">
<div class="btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-35px h-35px w-md-40px h-md-40px position-relative" id="support_ticket_toggle">
<span class="svg-icon svg-icon-1">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.3" d="M20 3H4C2.89543 3 2 3.89543 2 5V16C2 17.1046 2.89543 18 4 18H4.5C5.05228 18 5.5 18.4477 5.5 19V21.5052C5.5 22.1441 6.21212 22.5253 6.74376 22.1708L11.4885 19.0077C12.4741 18.3506 13.6321 18 14.8167 18H20C21.1046 18 22 17.1046 22 16V5C22 3.89543 21.1046 3 20 3Z" fill="currentColor"></path>
<rect x="6" y="12" width="7" height="2" rx="1" fill="currentColor"></rect>
<rect x="6" y="7" width="12" height="2" rx="1" fill="currentColor"></rect>
</svg>
</span>
</div>
</div>
<div class="app-navbar-item ms-1 ms-lg-3" id="kt_header_user_menu_toggle">
<div class="cursor-pointer symbol symbol-35px symbol-md-40px" data-kt-menu-trigger="click" data-kt-menu-attach="parent" data-kt-menu-placement="bottom-end">
<img alt="Avatar" src="/api/moonlight/avatar/@(User.Id)"/>
</div>
<div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-800 menu-state-bg menu-state-primary fw-semibold py-4 fs-6 w-275px" data-kt-menu="true">
<div class="menu-item px-3">
<div class="menu-content d-flex align-items-center px-3">
<div class="symbol symbol-50px me-5">
<img alt="Avatar" src="/api/moonlight/avatar/@(User.Id)"/>
</div>
<div class="d-flex flex-column">
<div class="fw-bold d-flex align-items-center fs-5">
@(User.FirstName) @(User.LastName)
@if (User.Admin)
{
<span class="badge badge-light-success fw-bold fs-8 px-2 py-1 ms-2">Admin</span>
}
</div>
<a class="fw-semibold text-muted text-hover-primary fs-7">@(User.Email)</a>
</div>
</div>
</div>
<div class="separator my-2"></div>
<div class="menu-item px-5 my-1">
<a href="/settings" class="menu-link px-5">@TranslationService.Translate("Navbar.Account.Settings")</a>
</div>
<div class="menu-item px-5">
<a @onclick="Logout" class="menu-link px-5">@TranslationService.Translate("Navbar.Logout")</a>
</div>
</div>
</div>
}
</div>
@code
{
private User? User;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
User = await IdentityService.Get();
await InvokeAsync(StateHasChanged);
}
}
private async void Logout()
{
await CookieService.SetValue("token", "", 1);
NavigationManager.NavigateTo(NavigationManager.Uri, true);
}
}

View file

@ -0,0 +1,29 @@
@using Moonlight.App.Services
@inject ConfigService ConfigService
@{
var moonlightConfig = ConfigService.GetSection("Moonlight");
}
<div id="kt_app_header" class="app-header">
<div class="app-container container-fluid d-flex align-items-stretch justify-content-between">
<div class="d-flex align-items-center d-lg-none ms-n2 me-2" title="Show sidebar menu">
<div class="btn btn-icon btn-active-color-primary w-35px h-35px" id="kt_app_sidebar_mobile_toggle">
<i class="bx bx-menu bx-md"></i>
</div>
</div>
<div class="d-flex align-items-center flex-grow-1 flex-lg-grow-0">
<a href="/" class="d-lg-none">
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logo.svg" class="h-30px"/>
</a>
</div>
<div class="d-flex align-items-stretch justify-content-between flex-lg-grow-1" id="kt_app_header_wrapper">
<div class="app-header-menu app-header-mobile-drawer align-items-stretch" data-kt-drawer="true" data-kt-drawer-name="app-header-menu" data-kt-drawer-activate="{default: true, lg: false}" data-kt-drawer-overlay="true" data-kt-drawer-width="225px" data-kt-drawer-direction="end" data-kt-drawer-toggle="#kt_app_header_menu_toggle" data-kt-swapper="true" data-kt-swapper-mode="{default: 'append', lg: 'prepend'}" data-kt-swapper-parent="{default: '#kt_app_body', lg: '#kt_app_header_wrapper'}">
<div class="menu menu-rounded menu-column menu-lg-row my-5 my-lg-0 align-items-stretch fw-semibold px-2 px-lg-0" id="kt_app_header_menu" data-kt-menu="true">
</div>
</div>
<Navbar></Navbar>
</div>
</div>
</div>

View file

@ -0,0 +1,63 @@
@using Moonlight.App.Services.Sessions
@using Moonlight.App.Database.Entities
@using Moonlight.App.Services
@inject IdentityService IdentityService
@inject TranslationService TranslationService
@inject ConfigService ConfigService
@inject IJSRuntime JsRuntime
@{
var moonlightConfig = ConfigService
.GetSection("Moonlight");
}
<div id="kt_app_sidebar" class="app-sidebar flex-column" data-kt-drawer="true" data-kt-drawer-name="app-sidebar" data-kt-drawer-activate="{default: true, lg: false}" data-kt-drawer-overlay="true" data-kt-drawer-width="225px" data-kt-drawer-direction="start" data-kt-drawer-toggle="#kt_app_sidebar_mobile_toggle">
<div class="app-sidebar-logo px-6" id="kt_app_sidebar_logo">
<a href="@(User != null ? "/" : "/login")">
@if (sidebar == "dark-sidebar")
{
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logofull.png" class="h-45px app-sidebar-logo-default"/>
}
else
{
if (sidebar == "light-sidebar")
{
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logo.svg" class="theme-light-show h-20px app-sidebar-logo-default"/>
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logo.svg" class="theme-dark-show h-20px app-sidebar-logo-default"/>
}
}
<img alt="Logo" src="@(moonlightConfig.GetValue<string>("AppUrl"))/api/moonlight/resources/images/logo.svg" class="h-20px app-sidebar-logo-minimize"/>
</a>
<div id="kt_app_sidebar_toggle" class="app-sidebar-toggle btn btn-icon btn-shadow btn-sm btn-color-muted btn-active-color-primary body-bg h-30px w-30px position-absolute top-50 start-100 translate-middle rotate" data-kt-toggle="true" data-kt-toggle-state="active" data-kt-toggle-target="body" data-kt-toggle-name="app-sidebar-minimize">
<i class="bx bx-chevrons-left bx-md"></i>
</div>
</div>
<SidebarMenu></SidebarMenu>
<div class="app-sidebar-footer flex-column-auto pt-2 pb-6 px-6" id="kt_app_sidebar_footer">
<a id="support_ticket_toggle_sidebar"
class="btn btn-flex flex-center btn-custom btn-primary overflow-hidden text-nowrap px-0 h-40px w-100 btn-label">
@(TranslationService.Translate("Sidebar.Footer.OpenSupport"))
</a>
</div>
</div>
@code
{
private string sidebar;
private User? User;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
User = await IdentityService.Get();
sidebar = await JsRuntime.InvokeAsync<string>("document.body.getAttribute", "data-kt-app-layout");
StateHasChanged();
}
}
}

View file

@ -0,0 +1,266 @@
@using Moonlight.App.Services
@using Moonlight.App.Services.Sessions
@using Moonlight.App.Database.Entities
@inject TranslationService TranslationService
@inject IdentityService IdentityService
<div class="app-sidebar-menu overflow-hidden flex-column-fluid">
<div id="kt_app_sidebar_menu_wrapper" class="app-sidebar-wrapper hover-scroll-overlay-y my-5" data-kt-scroll="true" data-kt-scroll-activate="true" data-kt-scroll-height="auto" data-kt-scroll-dependencies="#kt_app_sidebar_logo, #kt_app_sidebar_footer" data-kt-scroll-wrappers="#kt_app_sidebar_menu" data-kt-scroll-offset="5px" data-kt-scroll-save-state="true">
<div class="menu menu-column menu-rounded menu-sub-indention px-3" id="#kt_app_sidebar_menu" data-kt-menu="true" data-kt-menu-expand="false">
@if (User == null)
{
<div class="menu-item">
<a class="menu-link" href="/login">
<span class="menu-icon">
<i class="bx bxs-log-in"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Login")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/register">
<span class="menu-icon">
<i class="bx bx-user-plus"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Register")</span>
</a>
</div>
}
else
{
<div class="menu-item">
<a class="menu-link" href="/">
<span class="menu-icon">
<i class="bx bx-layer"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Dashboard")</span>
</a>
</div>
<div data-kt-menu-trigger="click" class="menu-item menu-accordion">
<span class="menu-link">
<span class="menu-icon">
<i class="bx bx-cart-alt"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Order")</span>
<span class="menu-arrow"></span>
</span>
<div class="menu-sub menu-sub-accordion">
<div class="menu-item">
<a class="menu-link" href="/store/website">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Website")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/store/database">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Database")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/store/domain">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Domain")</span>
</a>
</div>
</div>
</div>
<div class="menu-item">
<a class="menu-link" href="/servers">
<span class="menu-icon">
<i class="bx bx-server"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Servers")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/websites">
<span class="menu-icon">
<i class="bx bx-globe"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Websites")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/databases">
<span class="menu-icon">
<i class="bx bx-data"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Databases")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/domains">
<span class="menu-icon">
<i class="bx bx-purchase-tag"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Domains")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/changelog">
<span class="menu-icon">
<i class="bx bx-notepad"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Changelog")</span>
</a>
</div>
if (User.Admin)
{
<div class="menu-item pt-5">
<div class="menu-content">
<span class="menu-heading fw-bold text-uppercase fs-7">@TranslationService.Translate("Sidebar.Menu.Admin")</span>
</div>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin">
<span class="menu-icon">
<i class="bx bx-layer"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Dashboard")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/general">
<span class="menu-icon">
<i class="bx bx-chip"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.System")</span>
</a>
</div>
<div data-kt-menu-trigger="click" class="menu-item menu-accordion">
<span class="menu-link">
<span class="menu-icon">
<i class="bx bx-server"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Servers")</span>
<span class="menu-arrow"></span>
</span>
<div class="menu-sub menu-sub-accordion">
<div class="menu-item">
<a class="menu-link" href="/admin/servers">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Overview")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/servers/manager">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Manager")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/servers/cleanup">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Cleanup")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/nodes">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Nodes")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/images">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Images")</span>
</a>
</div>
</div>
</div>
<div data-kt-menu-trigger="click" class="menu-item menu-accordion">
<span class="menu-link">
<span class="menu-icon">
<i class="bx bx-cube"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.AaPanel")</span>
<span class="menu-arrow"></span>
</span>
<div class="menu-sub menu-sub-accordion">
<div class="menu-item">
<a class="menu-link" href="/admin/aapanel/">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Overview")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/aapanel/databases">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Databases")</span>
</a>
</div>
</div>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/users">
<span class="menu-icon">
<i class="bx bx-user"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Users")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/support">
<span class="menu-icon">
<i class="bx bx-support"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Support")</span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/statistics">
<span class="menu-icon">
<i class="bx bx-objects-vertical-bottom"></i>
</span>
<span class="menu-title">@TranslationService.Translate("Sidebar.Menu.Statistics")</span>
</a>
</div>
}
}
</div>
</div>
</div>
@code
{
private User? User;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
User = await IdentityService.Get();
await InvokeAsync(StateHasChanged);
}
}
}

View file

@ -0,0 +1,52 @@
@inject IJSRuntime JsRuntime
<a href="#" class="@ToggleBtnClass" data-kt-menu-trigger="@Trigger" data-kt-menu-attach="parent" data-kt-menu-placement="@MenuPlacement">
<i class="theme-light-show bx bx-sun"></i>
<i class="theme-dark-show bx bx-moon" ></i>
</a>
<div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-title-gray-700 menu-icon-muted menu-active-bg menu-state-primary fw-semibold py-4 fs-base w-175px" data-kt-menu="true" data-kt-element="theme-mode-menu">
<div class="menu-item px-3 my-0">
<a href="#" class="menu-link px-3 py-2" data-kt-element="mode" data-kt-value="light" @onclick="TriggerFlashbang">
<span class="menu-icon" data-kt-element="icon">
<i class="bx bx-sun"></i>
</span>
<span class="menu-title">Lightmode</span>
</a>
</div>
<div class="menu-item px-3 my-0">
<a href="#" class="menu-link px-3 py-2" data-kt-element="mode" data-kt-value="dark">
<span class="menu-icon" data-kt-element="icon">
<i class="bx bx-moon"></i>
</span>
<span class="menu-title">Darkmode</span>
</a>
</div>
<div class="menu-item px-3 my-0">
<a href="#" class="menu-link px-3 py-2" data-kt-element="mode" data-kt-value="system">
<span class="menu-icon" data-kt-element="icon">
<i class="bx bx-cog"></i>
</span>
<span class="menu-title">System</span>
</a>
</div>
</div>
@code {
[Parameter]
public string ToggleBtnClass { get; set; } = "";
[Parameter]
public string MenuPlacement { get; set; } = "bottom-end";
[Parameter]
public string ToggleBtnIconClass { get; set; } = "svg-icon svg-icon-2";
[Parameter]
public string Trigger { get; set; } = "{default:'click'}";
private async void TriggerFlashbang()
{
await JsRuntime.InvokeVoidAsync("flashbang");
}
}

View file

@ -0,0 +1,139 @@
@using Moonlight.Shared.Components.ErrorBoundaries
@using Moonlight.Shared.Components.Partials
@using Moonlight.Shared.Components.Alerts
@using Moonlight.App.Database.Entities
@using Moonlight.App.Models.Misc
@using Moonlight.App.Services.Sessions
@layout ThemeInit
@implements IDisposable
@inherits LayoutComponentBase
@inject IJSRuntime JsRuntime
@inject IdentityService IdentityService
@inject SessionService SessionService
@inject NavigationManager NavigationManager
<GlobalErrorBoundary>
<div class="d-flex flex-column flex-root app-root" id="kt_app_root">
<div class="app-page flex-column flex-column-fluid" id="kt_app_page">
<canvas id="snow" class="snow-canvas"></canvas>
@{
//TODO: Add a way to disable the snow
}
<PageHeader></PageHeader>
<div class="app-wrapper flex-column flex-row-fluid" id="kt_app_wrapper">
<Sidebar></Sidebar>
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
<div class="d-flex flex-column flex-column-fluid">
<div id="kt_app_content" class="app-content flex-column-fluid">
<div id="kt_app_content_container" class="app-container container-fluid">
<div class="mt-10">
<PageErrorBoundary>
@if (User == null)
{
@Body
}
else
{
if (User.Status == UserStatus.Banned)
{
<BannedAlert></BannedAlert>
}
else if (User.Status == UserStatus.Disabled)
{
<DisabledAlert></DisabledAlert>
}
else
{
@Body
}
}
</PageErrorBoundary>
</div>
</div>
</div>
</div>
<Footer></Footer>
</div>
</div>
</div>
</div>
</GlobalErrorBoundary>
@code
{
private User? User;
protected override void OnInitialized()
{
AddBodyAttribute("data-kt-app-page-loading", "on");
}
protected override void OnAfterRender(bool firstRender)
{
//Initialize classes and attributes for layout with dark sidebar
AddBodyAttribute("data-kt-app-reset-transition", "true");
AddBodyAttribute("data-kt-app-layout", "dark-sidebar");
AddBodyAttribute("data-kt-app-header-fixed", "true");
AddBodyAttribute("data-kt-app-sidebar-fixed", "true");
AddBodyAttribute("data-kt-app-sidebar-hoverable", "true");
AddBodyAttribute("data-kt-app-sidebar-push-header", "true");
AddBodyAttribute("data-kt-app-sidebar-push-toolbar", "true");
AddBodyAttribute("data-kt-app-sidebar-push-footer", "true");
AddBodyAttribute("data-kt-app-toolbar-enabled", "true");
AddBodyClass("app-default");
JsRuntime.InvokeVoidAsync("KTModalUpgradePlan.init");
JsRuntime.InvokeVoidAsync("KTCreateApp.init");
JsRuntime.InvokeVoidAsync("KTModalUserSearch.init");
JsRuntime.InvokeVoidAsync("KTModalNewTarget.init");
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
try
{
User = await IdentityService.Get();
await InvokeAsync(StateHasChanged);
await Task.Delay(300);
await JsRuntime.InvokeVoidAsync("document.body.removeAttribute", "data-kt-app-reset-transition");
await JsRuntime.InvokeVoidAsync("document.body.removeAttribute", "data-kt-app-page-loading");
await JsRuntime.InvokeVoidAsync("KTMenu.createInstances");
await JsRuntime.InvokeVoidAsync("KTDrawer.createInstances");
await JsRuntime.InvokeVoidAsync("createSnow");
await SessionService.Register();
NavigationManager.LocationChanged += (sender, args) => { SessionService.Refresh(); };
}
catch (Exception)
{
// ignored
}
}
}
public void Dispose()
{
SessionService.Close();
}
private void AddBodyAttribute(string attribute, string value)
{
JsRuntime.InvokeVoidAsync("document.body.setAttribute", attribute, value);
}
private void AddBodyClass(string className)
{
JsRuntime.InvokeVoidAsync("document.body.classList.add", className);
}
}

View file

@ -0,0 +1,78 @@
@inherits LayoutComponentBase
@inject IJSRuntime JS
@inject NavigationManager NavigationManager
@Body
<script suppress-error="BL9992">
window.emptyBody = function(){
document.body.className = '';
}
</script>
@code
{
protected override void OnAfterRender(bool firstRender)
{
JS.InvokeVoidAsync("KTThemeMode.init");
JS.InvokeVoidAsync("emptyBody");
if (firstRender)
{
JS.InvokeVoidAsync("scrollTo", 0, 0);
JS.InvokeVoidAsync("KTDialer.init");
JS.InvokeVoidAsync("KTDrawer.init");
JS.InvokeVoidAsync("KTMenu.init");
JS.InvokeVoidAsync("KTImageInput.init");
JS.InvokeVoidAsync("KTPasswordMeter.init");
JS.InvokeVoidAsync("KTScroll.init");
JS.InvokeVoidAsync("KTScrolltop.init");
JS.InvokeVoidAsync("KTSticky.init");
JS.InvokeVoidAsync("KTSwapper.init");
JS.InvokeVoidAsync("KTToggle.init");
JS.InvokeVoidAsync("KTMenu.updateByLinkAttribute", $"/{NavigationManager.ToBaseRelativePath(NavigationManager.Uri)}");
}
JS.InvokeVoidAsync("KTLayoutSearch.init");
JS.InvokeVoidAsync("KTAppSidebar.init");
}
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
private async void OnLocationChanged(object sender, LocationChangedEventArgs args)
{
await InvokeJsSave("scrollTo", 0, 0);
await InvokeJsSave("KTDrawer.createInstances");
await InvokeJsSave("KTMenu.createInstances");
await InvokeJsSave("KTImageInput.createInstances");
await InvokeJsSave("KTPasswordMeter.createInstances");
await InvokeJsSave("KTScroll.createInstances");
await InvokeJsSave("KTScrolltop.createInstances");
await InvokeJsSave("KTSticky.createInstances");
await InvokeJsSave("KTSwapper.createInstances");
await InvokeJsSave("KTToggle.createInstances");
await InvokeJsSave("KTMenu.updateByLinkAttribute", $"/{NavigationManager.ToBaseRelativePath(args.Location)}");
await InvokeJsSave("KTAppSidebar.init");
}
private async Task InvokeJsSave(string method, params object[] args)
{
try
{
await JS.InvokeVoidAsync(method, args);
}
catch (Exception)
{
// ignored
}
}
public void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
}
}

View file

@ -1,19 +0,0 @@
@inherits LayoutComponentBase
<PageTitle>Moonlight</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>

View file

@ -1,70 +0,0 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
}
.top-row a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row:not(.auth) {
display: none;
}
.top-row.auth {
justify-content: space-between;
}
.top-row a, .top-row .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}

View file

@ -1,39 +0,0 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">Moonlight</a>
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}

View file

@ -1,62 +0,0 @@
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}

View file

@ -1,16 +0,0 @@
<div class="alert alert-secondary mt-4">
<span class="oi oi-pencil me-2" aria-hidden="true"></span>
<strong>@Title</strong>
<span class="text-nowrap">
Please take our
<a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2149017">brief survey</a>
</span>
and tell us what you think.
</div>
@code {
// Demonstrates how a parent component can supply parameters
[Parameter]
public string? Title { get; set; }
}

View file

@ -0,0 +1,7 @@
@page "/"
<div class="card">
<div class="card-body">
x
</div>
</div>

View file

@ -7,4 +7,3 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Moonlight
@using Moonlight.Shared

View file

@ -15,38 +15,70 @@ build_property.GenerateRazorMetadataSourceChecksumAttributes =
build_property.MSBuildProjectDirectory = C:\Users\marce\source\repos\MoonlightPublic\Moonlight\Moonlight
build_property._RazorSourceGeneratorDebug =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/App.razor]
build_metadata.AdditionalFiles.TargetPath = QXBwLnJhem9y
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/BlazorApp.razor]
build_metadata.AdditionalFiles.TargetPath = Qmxhem9yQXBwLnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Pages/Counter.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcQ291bnRlci5yYXpvcg==
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Alerts/BannedAlert.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQWxlcnRzXEJhbm5lZEFsZXJ0LnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Pages/FetchData.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcRmV0Y2hEYXRhLnJhem9y
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Alerts/DisabledAlert.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcQWxlcnRzXERpc2FibGVkQWxlcnQucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Pages/Index.razor]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcSW5kZXgucmF6b3I=
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRXJyb3JCb3VuZGFyaWVzXENvbXBvbmVudEVycm9yQm91bmRhcnkucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/SurveyPrompt.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFN1cnZleVByb21wdC5yYXpvcg==
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/ErrorBoundaries/GlobalErrorBoundary.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRXJyb3JCb3VuZGFyaWVzXEdsb2JhbEVycm9yQm91bmRhcnkucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/ErrorBoundaries/PageErrorBoundary.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcRXJyb3JCb3VuZGFyaWVzXFBhZ2VFcnJvckJvdW5kYXJ5LnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/Footer.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcRm9vdGVyLnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/Navbar.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcTmF2YmFyLnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/PageHeader.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcUGFnZUhlYWRlci5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/Sidebar.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcU2lkZWJhci5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/SidebarMenu.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcU2lkZWJhck1lbnUucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Components/Partials/ThemeSwitcher.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXENvbXBvbmVudHNcUGFydGlhbHNcVGhlbWVTd2l0Y2hlci5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Layouts/MainLayout.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXExheW91dHNcTWFpbkxheW91dC5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Layouts/ThemeInit.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXExheW91dHNcVGhlbWVJbml0LnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/Views/Index.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXFZpZXdzXEluZGV4LnJhem9y
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/_Imports.razor]
build_metadata.AdditionalFiles.TargetPath = X0ltcG9ydHMucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/MainLayout.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXE1haW5MYXlvdXQucmF6b3I=
build_metadata.AdditionalFiles.CssScope = b-0cy8r6qmkj
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Shared/NavMenu.razor]
build_metadata.AdditionalFiles.TargetPath = U2hhcmVkXE5hdk1lbnUucmF6b3I=
build_metadata.AdditionalFiles.CssScope = b-h6mpglkmdc
[C:/Users/marce/source/repos/MoonlightPublic/Moonlight/Moonlight/Pages/Error.cshtml]
build_metadata.AdditionalFiles.TargetPath = UGFnZXNcRXJyb3IuY3NodG1s
build_metadata.AdditionalFiles.CssScope =

View file

@ -46,9 +46,95 @@
"net6.0": {
"targetAlias": "net6.0",
"dependencies": {
"BCrypt.Net-Next": {
"target": "Package",
"version": "[4.0.3, )"
},
"Ben.Demystifier": {
"target": "Package",
"version": "[0.4.1, )"
},
"Blazor.ContextMenu": {
"target": "Package",
"version": "[1.15.0, )"
},
"BlazorMonaco": {
"target": "Package",
"version": "[3.0.0, )"
},
"BlazorTable": {
"target": "Package",
"version": "[1.17.0, )"
},
"CurrieTechnologies.Razor.SweetAlert2": {
"target": "Package",
"version": "[5.4.0, )"
},
"Discord.Net": {
"target": "Package",
"version": "[3.9.0, )"
},
"GravatarSharp.Core": {
"target": "Package",
"version": "[0.9.0.2, )"
},
"JWT": {
"target": "Package",
"version": "[10.0.2, )"
},
"Logging.Net": {
"target": "Package",
"version": "[1.1.0, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[7.0.3, )"
},
"Microsoft.VisualStudio.Azure.Containers.Tools.Targets": {
"target": "Package",
"version": "[1.15.1, )"
},
"MineStat": {
"target": "Package",
"version": "[3.1.1, )"
},
"Newtonsoft.Json": {
"target": "Package",
"version": "[13.0.3-beta1, )"
},
"Otp.NET": {
"target": "Package",
"version": "[1.3.0, )"
},
"Pomelo.EntityFrameworkCore.MySql": {
"target": "Package",
"version": "[7.0.0, )"
},
"PteroConsole.NET": {
"target": "Package",
"version": "[1.0.4, )"
},
"QRCoder": {
"target": "Package",
"version": "[1.4.3, )"
},
"RestSharp": {
"target": "Package",
"version": "[109.0.0-preview.1, )"
},
"UAParser": {
"target": "Package",
"version": "[3.1.47, )"
},
"XtermBlazor": {
"target": "Package",
"version": "[1.6.1, )"
},
"aaPanelSharp": {
"target": "Package",
"version": "[1.0.0, )"
}
},
"imports": [

View file

@ -15,7 +15,14 @@
<SourceRoot Include="C:\Program Files\dotnet\sdk\NuGetFallbackFolder\" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xtermblazor\1.6.1\buildTransitive\XtermBlazor.props" Condition="Exists('$(NuGetPackageRoot)xtermblazor\1.6.1\buildTransitive\XtermBlazor.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.3\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\7.0.3\buildTransitive\net6.0\Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.visualstudio.azure.containers.tools.targets\1.15.1\build\Microsoft.VisualStudio.Azure.Containers.Tools.Targets.props" Condition="Exists('$(NuGetPackageRoot)microsoft.visualstudio.azure.containers.tools.targets\1.15.1\build\Microsoft.VisualStudio.Azure.Containers.Tools.Targets.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\7.0.3\build\net6.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\7.0.3\build\net6.0\Microsoft.EntityFrameworkCore.Design.props')" />
<Import Project="$(NuGetPackageRoot)currietechnologies.razor.sweetalert2\5.4.0\buildTransitive\CurrieTechnologies.Razor.SweetAlert2.props" Condition="Exists('$(NuGetPackageRoot)currietechnologies.razor.sweetalert2\5.4.0\buildTransitive\CurrieTechnologies.Razor.SweetAlert2.props')" />
<Import Project="$(NuGetPackageRoot)blazortable\1.17.0\buildTransitive\BlazorTable.props" Condition="Exists('$(NuGetPackageRoot)blazortable\1.17.0\buildTransitive\BlazorTable.props')" />
<Import Project="$(NuGetPackageRoot)blazormonaco\3.0.0\buildTransitive\BlazorMonaco.props" Condition="Exists('$(NuGetPackageRoot)blazormonaco\3.0.0\buildTransitive\BlazorMonaco.props')" />
<Import Project="$(NuGetPackageRoot)blazor.contextmenu\1.15.0\buildTransitive\Blazor.ContextMenu.props" Condition="Exists('$(NuGetPackageRoot)blazor.contextmenu\1.15.0\buildTransitive\Blazor.ContextMenu.props')" />
</ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<PkgMicrosoft_VisualStudio_Azure_Containers_Tools_Targets Condition=" '$(PkgMicrosoft_VisualStudio_Azure_Containers_Tools_Targets)' == '' ">C:\Users\marce\.nuget\packages\microsoft.visualstudio.azure.containers.tools.targets\1.15.1</PkgMicrosoft_VisualStudio_Azure_Containers_Tools_Targets>

View file

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\7.0.0\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.components.analyzers\6.0.9\buildTransitive\netstandard2.0\Microsoft.AspNetCore.Components.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.components.analyzers\6.0.9\buildTransitive\netstandard2.0\Microsoft.AspNetCore.Components.Analyzers.targets')" />
<Import Project="$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\7.0.0\buildTransitive\net6.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.visualstudio.azure.containers.tools.targets\1.15.1\build\Microsoft.VisualStudio.Azure.Containers.Tools.Targets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.visualstudio.azure.containers.tools.targets\1.15.1\build\Microsoft.VisualStudio.Azure.Containers.Tools.Targets.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,87 @@
{
"version": 2,
"dgSpecHash": "yy/NjlE13jUBAfYW0Jby0Um0q1bacbuKsTzQSymbyV/SUAbvE/vTqe61sVtjo+aDJhhfe6IkK+vrTFEXlUUEoA==",
"dgSpecHash": "kweG9cyheq0lvUg6tPkk+sPoY2pPlReL0QP5jHLJNWl9pUpDd+CJp7bLfFE9WjjPi9DegeiFh5tJQ1eO1r96RA==",
"success": true,
"projectFilePath": "C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\Moonlight.csproj",
"expectedPackageFiles": [
"C:\\Users\\marce\\.nuget\\packages\\microsoft.visualstudio.azure.containers.tools.targets\\1.15.1\\microsoft.visualstudio.azure.containers.tools.targets.1.15.1.nupkg.sha512"
"C:\\Users\\marce\\.nuget\\packages\\aapanelsharp\\1.0.0\\aapanelsharp.1.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\bcrypt.net-next\\4.0.3\\bcrypt.net-next.4.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\ben.demystifier\\0.4.1\\ben.demystifier.0.4.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\blazor.contextmenu\\1.15.0\\blazor.contextmenu.1.15.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\blazormonaco\\3.0.0\\blazormonaco.3.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\blazortable\\1.17.0\\blazortable.1.17.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\currietechnologies.razor.sweetalert2\\5.4.0\\currietechnologies.razor.sweetalert2.5.4.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net\\3.9.0\\discord.net.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.commands\\3.9.0\\discord.net.commands.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.core\\3.9.0\\discord.net.core.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.interactions\\3.9.0\\discord.net.interactions.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.rest\\3.9.0\\discord.net.rest.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.webhook\\3.9.0\\discord.net.webhook.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\discord.net.websocket\\3.9.0\\discord.net.websocket.3.9.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\gravatarsharp.core\\0.9.0.2\\gravatarsharp.core.0.9.0.2.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\jwt\\10.0.2\\jwt.10.0.2.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\linqkit.core\\1.1.26\\linqkit.core.1.1.26.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\logging.net\\1.1.0\\logging.net.1.1.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\macross.json.extensions\\3.0.0\\macross.json.extensions.3.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.authorization\\6.0.9\\microsoft.aspnetcore.authorization.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.components\\6.0.9\\microsoft.aspnetcore.components.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.components.analyzers\\6.0.9\\microsoft.aspnetcore.components.analyzers.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.components.forms\\6.0.9\\microsoft.aspnetcore.components.forms.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.components.web\\6.0.9\\microsoft.aspnetcore.components.web.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.aspnetcore.metadata\\6.0.9\\microsoft.aspnetcore.metadata.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.entityframeworkcore\\7.0.3\\microsoft.entityframeworkcore.7.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\7.0.3\\microsoft.entityframeworkcore.abstractions.7.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\7.0.3\\microsoft.entityframeworkcore.analyzers.7.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.entityframeworkcore.design\\7.0.3\\microsoft.entityframeworkcore.design.7.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\7.0.3\\microsoft.entityframeworkcore.relational.7.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\7.0.0\\microsoft.extensions.caching.abstractions.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.caching.memory\\7.0.0\\microsoft.extensions.caching.memory.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\7.0.0\\microsoft.extensions.configuration.abstractions.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\7.0.0\\microsoft.extensions.dependencyinjection.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\7.0.0\\microsoft.extensions.dependencyinjection.abstractions.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.dependencymodel\\7.0.0\\microsoft.extensions.dependencymodel.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.localization\\3.1.18\\microsoft.extensions.localization.3.1.18.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.localization.abstractions\\3.1.18\\microsoft.extensions.localization.abstractions.3.1.18.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.logging\\7.0.0\\microsoft.extensions.logging.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\7.0.0\\microsoft.extensions.logging.abstractions.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.options\\7.0.0\\microsoft.extensions.options.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.extensions.primitives\\7.0.0\\microsoft.extensions.primitives.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.jsinterop\\6.0.9\\microsoft.jsinterop.6.0.9.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\microsoft.visualstudio.azure.containers.tools.targets\\1.15.1\\microsoft.visualstudio.azure.containers.tools.targets.1.15.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\minestat\\3.1.1\\minestat.3.1.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\mono.texttemplating\\2.2.1\\mono.texttemplating.2.2.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\mysqlconnector\\2.2.5\\mysqlconnector.2.2.5.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\newtonsoft.json\\13.0.3-beta1\\newtonsoft.json.13.0.3-beta1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\otp.net\\1.3.0\\otp.net.1.3.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\pomelo.entityframeworkcore.mysql\\7.0.0\\pomelo.entityframeworkcore.mysql.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\pteroconsole.net\\1.0.4\\pteroconsole.net.1.0.4.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\qrcoder\\1.4.3\\qrcoder.1.4.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\restsharp\\109.0.0-preview.1\\restsharp.109.0.0-preview.1.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.codedom\\4.4.0\\system.codedom.4.4.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.collections.immutable\\5.0.0\\system.collections.immutable.5.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.interactive.async\\5.0.0\\system.interactive.async.5.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.io.pipelines\\6.0.3\\system.io.pipelines.6.0.3.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.linq.async\\5.0.0\\system.linq.async.5.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.reactive\\5.0.0\\system.reactive.5.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.reflection.metadata\\5.0.0\\system.reflection.metadata.5.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\6.0.0\\system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.text.encodings.web\\7.0.0\\system.text.encodings.web.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.text.json\\7.0.0\\system.text.json.7.0.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\system.valuetuple\\4.5.0\\system.valuetuple.4.5.0.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\uaparser\\3.1.47\\uaparser.3.1.47.nupkg.sha512",
"C:\\Users\\marce\\.nuget\\packages\\xtermblazor\\1.6.1\\xtermblazor.1.6.1.nupkg.sha512"
],
"logs": []
"logs": [
{
"code": "NU1701",
"level": "Warning",
"warningLevel": 1,
"message": "Package 'GravatarSharp.Core 0.9.0.2' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework 'net6.0'. This package may not be fully compatible with your project.",
"libraryId": "GravatarSharp.Core",
"targetGraphs": [
"net6.0"
]
}
]
}

View file

@ -1 +1 @@
"restore":{"projectUniqueName":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\Moonlight.csproj","projectName":"Moonlight","projectPath":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\Moonlight.csproj","outputPath":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages","C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"],"originalTargetFrameworks":["net6.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"C:\\Users\\marce\\source\\repos\\Logging.Net\\LoggingNet\\LoggingNet\\bin\\Release\\net5.0\\newpublish":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net6.0":{"targetAlias":"net6.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]}}"frameworks":{"net6.0":{"targetAlias":"net6.0","dependencies":{"Microsoft.VisualStudio.Azure.Containers.Tools.Targets":{"target":"Package","version":"[1.15.1, )"}},"imports":["net461","net462","net47","net471","net472","net48"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.AspNetCore.App":{"privateAssets":"none"},"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\6.0.300\\RuntimeIdentifierGraph.json"}}
"restore":{"projectUniqueName":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\Moonlight.csproj","projectName":"Moonlight","projectPath":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\Moonlight.csproj","outputPath":"C:\\Users\\marce\\source\\repos\\MoonlightPublic\\Moonlight\\Moonlight\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages","C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"],"originalTargetFrameworks":["net6.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"C:\\Users\\marce\\source\\repos\\Logging.Net\\LoggingNet\\LoggingNet\\bin\\Release\\net5.0\\newpublish":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net6.0":{"targetAlias":"net6.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]}}"frameworks":{"net6.0":{"targetAlias":"net6.0","dependencies":{"BCrypt.Net-Next":{"target":"Package","version":"[4.0.3, )"},"Ben.Demystifier":{"target":"Package","version":"[0.4.1, )"},"Blazor.ContextMenu":{"target":"Package","version":"[1.15.0, )"},"BlazorMonaco":{"target":"Package","version":"[3.0.0, )"},"BlazorTable":{"target":"Package","version":"[1.17.0, )"},"CurrieTechnologies.Razor.SweetAlert2":{"target":"Package","version":"[5.4.0, )"},"Discord.Net":{"target":"Package","version":"[3.9.0, )"},"GravatarSharp.Core":{"target":"Package","version":"[0.9.0.2, )"},"JWT":{"target":"Package","version":"[10.0.2, )"},"Logging.Net":{"target":"Package","version":"[1.1.0, )"},"Microsoft.EntityFrameworkCore.Design":{"include":"Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive","suppressParent":"All","target":"Package","version":"[7.0.3, )"},"Microsoft.VisualStudio.Azure.Containers.Tools.Targets":{"target":"Package","version":"[1.15.1, )"},"MineStat":{"target":"Package","version":"[3.1.1, )"},"Newtonsoft.Json":{"target":"Package","version":"[13.0.3-beta1, )"},"Otp.NET":{"target":"Package","version":"[1.3.0, )"},"Pomelo.EntityFrameworkCore.MySql":{"target":"Package","version":"[7.0.0, )"},"PteroConsole.NET":{"target":"Package","version":"[1.0.4, )"},"QRCoder":{"target":"Package","version":"[1.4.3, )"},"RestSharp":{"target":"Package","version":"[109.0.0-preview.1, )"},"UAParser":{"target":"Package","version":"[3.1.47, )"},"XtermBlazor":{"target":"Package","version":"[1.6.1, )"},"aaPanelSharp":{"target":"Package","version":"[1.0.0, )"}},"imports":["net461","net462","net47","net471","net472","net48"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.AspNetCore.App":{"privateAssets":"none"},"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\6.0.300\\RuntimeIdentifierGraph.json"}}

View file

@ -0,0 +1,67 @@
{
"Crashes": {
"Component": {
"Title": "Ooops. Something went wrong",
"Details": "This component has crashed"
},
"Page": {
"Title": "Ooops. Something went wrong",
"Details": "This site has crashed"
},
"Global": {
"Title": "Ooops. Something went wrong",
"Details": "Your moonlight client has crashed"
}
},
"Footer": {
"AboutUs": "About us",
"Imprint": "Imprint",
"Privacy": "Privacy"
},
"Alerts": {
"Banned": {
"Title": "Your account is banned from moonlight",
"Details": "Your data will be deleted shortly. For more information contact support"
},
"Disabled": {
"Title": "Your account is temporary banned from moonlight",
"Details": "Your data is is still saved but the access to it is not possible at this time. For more information contact support"
}
},
"Navbar": {
"Account": {
"Settings": "Account settings"
},
"Logout": "Logout"
},
"Sidebar": {
"Footer": {
"OpenSupport": "Open support"
},
"Menu": {
"Login": "Login",
"Register": "Register",
"Dashboard": "Dashboard",
"Order": "Order",
"Website": "Website",
"Database": "Database",
"Domain": "Domain",
"Servers": "Servers",
"Websites": "Websites",
"Databases": "Databases",
"Domains": "Domains",
"Changelog": "Changelog",
"Admin": "Admin",
"System": "System",
"Overview": "Overview",
"Manager": "Manager",
"Cleanup": "Cleanup",
"Nodes": "Nodes",
"Images": "Images",
"AaPanel": "AaPanel",
"Users": "Users",
"Support": "Support",
"Statistics": "Statistics"
}
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="256px" height="301px" viewBox="0 0 256 301" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
<defs>
<linearGradient x1="2.17771739%" y1="34.7938955%" x2="92.7221942%" y2="91.3419405%" id="linearGradient-1">
<stop stop-color="#41A7EF" offset="0%"></stop>
<stop stop-color="#813DDE" offset="54.2186236%"></stop>
<stop stop-color="#8F2EE2" offset="74.4988788%"></stop>
<stop stop-color="#A11CE6" offset="100%"></stop>
</linearGradient>
</defs>
<g>
<path d="M124.183681,101.699 C124.183681,66.515 136.256681,34.152 156.486681,8.525 C159.197681,5.092 156.787681,0.069 152.412681,0.012 C151.775681,0.004 151.136681,0 150.497681,0 C67.6206813,0 0.390681343,66.99 0.00168134279,149.775 C-0.386318657,232.369 66.4286813,300.195 149.019681,300.988 C189.884681,301.381 227.036681,285.484 254.376681,259.395 C257.519681,256.396 255.841681,251.082 251.548681,250.42 C179.413681,239.291 124.183681,176.949 124.183681,101.699" fill="url(#linearGradient-1)"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,58 @@
.my-reconnect-modal {
display: none;
}
.my-reconnect-modal > div {
position: fixed;
inset: 0px;
z-index: 1050;
overflow: hidden;
text-align: center;
font-weight: bold;
transition: visibility 0s linear 500ms;
backdrop-filter: blur(20px);
background-color: #0008;
}
.components-reconnect-hide > div {
display: none;
}
.components-reconnect-show > div {
display: none;
}
.components-reconnect-show > .show {
display: block;
}
.components-reconnect-failed > div {
display: none;
}
.components-reconnect-failed > .failed {
display: block;
}
.components-reconnect-rejected > div {
display: none;
}
.components-reconnect-rejected > .rejected {
display: block;
}
.components-reconnect-hide > div {
display: none;
}
.components-reconnect-show {
display: block;
}
.components-reconnect-failed {
display: block;
}
.components-reconnect-rejected {
display: block;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,38 @@
@keyframes flashbang {
0% {
opacity: 0;
}
1% {
opacity: 0.7;
}
2% {
opacity: 1;
}
45% {
opacity: 1;
}
50% {
opacity: 0.8;
}
55% {
opacity: 0.7;
}
90% {
opacity: 0.3;
}
100% {
opacity: 0;
}
}
.flashbanglight {
top: 50%;
left: 50%;
opacity: 1;
width: 1px;
height: 1px;
border-radius: 100%;
background: transparent;
z-index: 999;
color: gold;
}

View file

@ -0,0 +1,9 @@
.invisible-a {
color: inherit;
cursor: pointer;
}
.invisible-a:hover {
color: inherit;
cursor: pointer;
}

View file

@ -0,0 +1,9 @@
.snow-canvas {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
pointer-events: none;
}

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,68 @@
window.showAlertInfo = function (title, description)
{
Swal.fire(
title,
description,
'info'
)
}
window.showAlertSuccess = function (title, description)
{
Swal.fire(
title,
description,
'success'
)
}
window.showAlertWarning = function (title, description)
{
Swal.fire(
title,
description,
'warning'
)
}
window.showAlertError = function (title, description)
{
Swal.fire(
title,
description,
'error'
)
}
window.showAlertYesNo = function (title, yesText, noText)
{
return Swal.fire({
title: title,
showDenyButton: true,
confirmButtonText: yesText,
denyButtonText: noText,
}).then((result) => {
if (result.isConfirmed) {
return true;
} else if (result.isDenied) {
return false;
}
})
}
window.showAlertText = function (title, description) {
const {value: text} = Swal.fire({
title: title,
input: 'text',
inputLabel: description,
inputValue: "",
showCancelButton: false,
inputValidator: (value) => {
if (!value) {
return 'Es muss ein Wert angegeben werden'
}
}
})
return text;
}

View file

@ -0,0 +1,32 @@
function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
// Avoid scrolling to bottom
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text);
return;
}
navigator.clipboard.writeText(text).then(function() {
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
}

View file

@ -0,0 +1,143 @@
window.initConsolePlugins = function () {
window.XtermBlazor.registerAddon("xterm-addon-fit", new window.FitAddon.FitAddon());
addEventListener('resize', (event) => {
//XtermBlazor.invokeAddonFunction()
});
};
window.initGraphs = function () {
};
window.initCpu = function () {
var element = document.getElementById('cpuchart');
var height = parseInt(KTUtil.css(element, 'height'));
var labelColor = KTUtil.getCssVariableValue('--kt-gray-500');
var borderColor = KTUtil.getCssVariableValue('--kt-gray-200');
var baseColor = KTUtil.getCssVariableValue('--kt-info');
var lightColor = KTUtil.getCssVariableValue('--kt-info-light');
if (!element) {
return;
}
var options = {
series: [{
name: 'CPU Auslastung',
data: [0, 0, 0, 0, 0, 0, 0]
}],
chart: {
fontFamily: 'inherit',
type: 'area',
height: height,
toolbar: {
show: false
}
},
plotOptions: {},
legend: {
show: false
},
dataLabels: {
enabled: false
},
fill: {
type: 'solid',
opacity: 1
},
stroke: {
curve: 'smooth',
show: true,
width: 3,
colors: [baseColor]
},
xaxis: {
categories: [],
axisBorder: {
show: false,
},
axisTicks: {
show: false
},
labels: {
style: {
colors: labelColor,
fontSize: '12px'
}
},
crosshairs: {
position: 'front',
stroke: {
color: baseColor,
width: 1,
dashArray: 3
}
},
tooltip: {
enabled: false,
formatter: undefined,
offsetY: 0,
style: {
fontSize: '12px'
}
}
},
yaxis: {
labels: {
style: {
colors: labelColor,
fontSize: '12px'
}
}
},
states: {
normal: {
filter: {
type: 'none',
value: 0
}
},
hover: {
filter: {
type: 'none',
value: 0
}
},
active: {
allowMultipleDataPointsSelection: false,
filter: {
type: 'none',
value: 0
}
}
},
colors: [lightColor],
grid: {
borderColor: borderColor,
strokeDashArray: 4,
yaxis: {
lines: {
show: true
}
}
},
markers: {
strokeColor: baseColor,
strokeWidth: 3
}
};
var chart = new ApexCharts(element, options);
chart.render();
window.console.cpuchart = chart;
};
window.updateCpu = function (value) {
window.console.cpuchart.appendSeries({
name: 'CPU Auslastung',
data: value
});
};

View file

@ -0,0 +1,26 @@
window.setCookie = function (key, value, days) {
const d = new Date();
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
let expires = "expires=" + d.toUTCString();
document.cookie = key + "=" + value + ";" + expires + ";path=/";
}
window.deleteCookie = function (key) {
window.setCookie(key, "", 0);
}
window.getCookie = function (cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}

View file

@ -0,0 +1,12 @@
function flashbang() {
const light = document.getElementById("flashbang");
light.style.boxShadow = "0 0 10000px 10000px white, 0 0 250px 10px #FFFFFF";
light.style.animation = "flashbang 5s linear forwards";
light.onanimationend = clearFlashbang;
}
function clearFlashbang() {
const light = document.getElementById("flashbang");
light.style.animation = "";
light.style.opacity = "0";
}

View file

@ -0,0 +1,51 @@
window.logInfo = function (prefix, message)
{
console.log(
'%c[%cINFO%c] [%c' + prefix + '%c] %c' + message,
'color: white', // [
'color: aqua', // INFO
'color: white', // ]
'color: purple', // {prefix}
'color: white', // ]
'color: lightgray' // {message}
);
};
window.logWarn = function (prefix, message)
{
console.log(
'%c[%cWARN%c] [%c' + prefix + '%c] %c' + message,
'color: white', // [
'color: orange', // WARN
'color: white', // ]
'color: purple', // {prefix}
'color: white', // ]
'color: lightgray' // {message}
);
};
window.logError = function (prefix, message)
{
console.log(
'%c[%cERROR%c] [%c' + prefix + '%c] %c' + message,
'color: white', // [
'color: red', // ERROR
'color: white', // ]
'color: purple', // {prefix}
'color: white', // ]
'color: lightgray' // {message}
);
};
window.logDebug = function (prefix, message)
{
console.log(
'%c[%cDEBUG%c] [%c' + prefix + '%c] %c' + message,
'color: white', // [
'color: green', // DEBUG
'color: white', // ]
'color: purple', // {prefix}
'color: white', // ]
'color: lightgray' // {message}
);
};

View file

@ -0,0 +1 @@
require.config({ paths: { 'vs': '_content/BlazorMonaco/lib/monaco-editor/min/vs' } });

View file

@ -0,0 +1,9 @@
window.recaptcha = new Object();
window.recaptcha.render = function (id, sitekey, page)
{
return grecaptcha.render(id, {
'sitekey': sitekey,
'callback': (response) => { page.invokeMethodAsync('CallbackOnSuccess', response); },
'expired-callback': () => { page.invokeMethodAsync('CallbackOnExpired'); }
});
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,118 @@
window.createSnow = function () {
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
var flakes = [],
canvas = document.getElementById("snow"),
ctx = canvas.getContext("2d"),
flakeCount = 200,
mX = -100,
mY = -100
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function snow() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < flakeCount; i++) {
var flake = flakes[i],
x = mX,
y = mY,
minDist = 150,
x2 = flake.x,
y2 = flake.y;
var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
dx = x2 - x,
dy = y2 - y;
if (dist < minDist) {
var force = minDist / (dist * dist),
xcomp = (x - x2) / dist,
ycomp = (y - y2) / dist,
deltaV = force / 2;
flake.velX -= deltaV * xcomp;
flake.velY -= deltaV * ycomp;
} else {
flake.velX *= .98;
if (flake.velY <= flake.speed) {
flake.velY = flake.speed
}
flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
}
ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")";
flake.y += flake.velY;
flake.x += flake.velX;
if (flake.y >= canvas.height || flake.y <= 0) {
reset(flake);
}
if (flake.x >= canvas.width || flake.x <= 0) {
reset(flake);
}
ctx.beginPath();
ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
ctx.fill();
}
requestAnimationFrame(snow);
};
function reset(flake) {
flake.x = Math.floor(Math.random() * canvas.width);
flake.y = 0;
flake.size = (Math.random() * 3) + 2;
flake.speed = (Math.random() * 1) + 0.5;
flake.velY = flake.speed;
flake.velX = 0;
flake.opacity = (Math.random() * 0.5) + 0.3;
}
function init() {
for (var i = 0; i < flakeCount; i++) {
var x = Math.floor(Math.random() * canvas.width),
y = Math.floor(Math.random() * canvas.height),
size = (Math.random() * 3) + 2,
speed = (Math.random() * 1) + 0.5,
opacity = (Math.random() * 0.5) + 0.3;
flakes.push({
speed: speed,
velY: speed,
velX: 0,
x: x,
y: y,
size: size,
stepSize: (Math.random()) / 30,
step: 0,
opacity: opacity
});
}
snow();
};
canvas.addEventListener("mousemove", function (e) {
mX = e.clientX,
mY = e.clientY
});
window.addEventListener("resize", function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
})
init();
}

View file

@ -0,0 +1,14 @@
if (document.documentElement) {
const defaultThemeMode = "dark";
const name = document.body.getAttribute("data-kt-name");
let themeMode = localStorage.getItem("kt_" + (name !== null ? name + "_" : "") + "theme_mode_value");
if (themeMode === null) {
if (defaultThemeMode === "system") {
themeMode = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
} else {
themeMode = defaultThemeMode;
}
}
document.documentElement.setAttribute("data-theme", themeMode);
}

Some files were not shown because too many files have changed in this diff Show more