Remove old v2 structure

This commit is contained in:
Marcel Baumgartner 2024-03-18 09:30:30 +01:00
parent 823970f617
commit 15a3789174
818 changed files with 0 additions and 61493 deletions

View file

@ -1,25 +0,0 @@
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.idea
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

10
.gitattributes vendored
View file

@ -1,10 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
Moonlight/wwwroot/** linguist-vendored
Moonlight/wwwroot/assets/js/scripts.bundle.js linguist-vendored
Moonlight/wwwroot/assets/js/widgets.bundle.js linguist-vendored
Moonlight/wwwroot/assets/js/theme.js linguist-vendored
Moonlight/wwwroot/assets/css/boxicons.min.css linguist-vendored
Moonlight/wwwroot/assets/css/style.bundle.css linguist-vendored
Moonlight/wwwroot/assets/plugins/** linguist-vendored
Moonlight/wwwroot/assets/fonts/** linguist-vendored

44
.gitignore vendored
View file

@ -1,44 +0,0 @@
 Common IntelliJ Platform excludes
# User specific
**/.idea/**/workspace.xml
**/.idea/**/tasks.xml
**/.idea/shelf/*
**/.idea/dictionaries
**/.idea/httpRequests/
# Sensitive or high-churn files
**/.idea/**/dataSources/
**/.idea/**/dataSources.ids
**/.idea/**/dataSources.xml
**/.idea/**/dataSources.local.xml
**/.idea/**/sqlDataSources.xml
**/.idea/**/dynamic.xml
# Rider
# Rider auto-generates .iml files, and contentModel.xml
**/.idea/**/*.iml
**/.idea/**/contentModel.xml
**/.idea/**/modules.xml
Moonlight/[Bb]in/
Moonlight/[Oo]bj/
Moonlight/_UpgradeReport_Files/
Moonlight/[Pp]ackages/
*.suo
*.user
.vs/
[Bb]in/
[Oo]bj/
_UpgradeReport_Files/
[Pp]ackages/
Thumbs.db
Desktop.ini
.DS_Store
.idea/.idea.Moonlight/.idea/discord.xml
Moonlight/wwwroot/css/theme.css
Moonlight/wwwroot/css/theme.css.map
storage/

View file

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EfCoreCommonOptions">
<option name="migrationsToStartupProjects">
<map>
<entry key="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
</map>
</option>
<option name="solutionLevelOptions">
<map>
<entry key="migrationsProject" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
<entry key="startupProject" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
</map>
</option>
<option name="startupToMigrationsProjects">
<map>
<entry key="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
</map>
</option>
</component>
</project>

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EfCoreDialogsState">
<option name="keyValueStorage">
<map>
<entry key="Common:691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da:dbContext" value="Moonlight.App.Database.DataContext" />
<entry key="Common:buildConfiguration" value="Debug" />
<entry key="Common:noBuild" value="false" />
<entry key="Common:outputFolder" value="App/Database/Migrations" />
</map>
</option>
</component>
</project>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -1,16 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moonlight", "Moonlight\Moonlight.csproj", "{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View file

@ -1,15 +0,0 @@
@using Moonlight.Core.UI.Layouts
<Router AppAssembly="@typeof(BlazorApp).Assembly">
<Found Context="routeData">
<CascadingValue TValue="Type" Name="TargetPageType" Value="routeData.PageType">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
</CascadingValue>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View file

@ -1,22 +0,0 @@
using Moonlight.Features.ServiceManagement.Entities;
using Moonlight.Features.ServiceManagement.Models.Abstractions;
namespace Moonlight.Core.Actions.Dummy;
public class DummyActions : ServiceActions
{
public override Task Create(IServiceProvider provider, Service service)
{
return Task.CompletedTask;
}
public override Task Update(IServiceProvider provider, Service service)
{
return Task.CompletedTask;
}
public override Task Delete(IServiceProvider provider, Service service)
{
return Task.CompletedTask;
}
}

View file

@ -1,11 +0,0 @@
using System.ComponentModel;
namespace Moonlight.Core.Actions.Dummy;
public class DummyConfig
{
[Description("Some description")]
public string String { get; set; } = "";
public bool Boolean { get; set; }
public int Integer { get; set; }
}

View file

@ -1,24 +0,0 @@
using Moonlight.Core.Actions.Dummy.Layouts;
using Moonlight.Core.Actions.Dummy.Pages;
using Moonlight.Features.ServiceManagement.Models.Abstractions;
namespace Moonlight.Core.Actions.Dummy;
public class DummyServiceDefinition : ServiceDefinition
{
public override ServiceActions Actions => new DummyActions();
public override Type ConfigType => typeof(DummyConfig);
public override async Task BuildUserView(ServiceViewContext context)
{
context.Layout = typeof(DummyUser);
await context.AddPage<DummyPage>("Demo", "/demo");
}
public override Task BuildAdminView(ServiceViewContext context)
{
context.Layout = typeof(DummyAdmin);
return Task.CompletedTask;
}
}

View file

@ -1,5 +0,0 @@
<h3>DummyAdmin</h3>
@code {
}

View file

@ -1,5 +0,0 @@
<h3>DummyUser</h3>
@code {
}

View file

@ -1,5 +0,0 @@
<h3>DummyPage</h3>
@code {
}

View file

@ -1,95 +0,0 @@
using System.ComponentModel;
using MoonCore.Helpers;
using Moonlight.Features.Advertisement.Configuration;
using Moonlight.Features.FileManager.Configuration;
using Moonlight.Features.Servers.Configuration;
using Moonlight.Features.StoreSystem.Configuration;
using Moonlight.Features.Theming.Configuration;
using Newtonsoft.Json;
namespace Moonlight.Core.Configuration;
public class ConfigV1
{
[JsonProperty("AppUrl")]
[Description("The url with which moonlight is accessible from the internet. It must not end with a /")]
public string AppUrl { get; set; } = "http://your-moonlight-instance-without-slash.owo";
[JsonProperty("Security")] public SecurityData Security { get; set; } = new();
[JsonProperty("Database")] public DatabaseData Database { get; set; } = new();
[JsonProperty("MailServer")] public MailServerData MailServer { get; set; } = new();
[JsonProperty("Store")] public StoreData Store { get; set; } = new();
[JsonProperty("Theme")] public ThemeData Theme { get; set; } = new();
[JsonProperty("Advertisement")] public AdvertisementData Advertisement { get; set; } = new();
[JsonProperty("FileManager")] public FileManagerData FileManager { get; set; } = new();
[JsonProperty("WebServer")] public WebServerData WebServer { get; set; } = new();
[JsonProperty("Servers")] public ServersData Servers { get; set; } = new();
public class WebServerData
{
[JsonProperty("HttpUploadLimit")]
[Description("This sets the kestrel upload limit in megabytes. Changing this will need an restart")]
public int HttpUploadLimit { get; set; } = 100 * 1024;
}
public class SecurityData
{
[JsonProperty("Token")]
[Description("The security token helio will use to encrypt various things like tokens")]
public string Token { get; set; } = Guid.NewGuid().ToString().Replace("-", "");
[JsonProperty("EnableEmailVerify")]
[Description("This will users force to verify their email address if they havent already")]
public bool EnableEmailVerify { get; set; } = false;
[JsonProperty("EnableReverseProxyMode")]
[Description("Enable this option if you are using a reverse proxy to access moonlight. This will configure some parts of moonlight to act correctly like the ip detection")]
public bool EnableReverseProxyMode { get; set; } = false;
}
public class DatabaseData
{
[JsonProperty("UseSqlite")]
public bool UseSqlite { get; set; } = false;
[JsonProperty("SqlitePath")]
public string SqlitePath { get; set; } = PathBuilder.File("storage", "data.sqlite");
[JsonProperty("Host")]
public string Host { get; set; } = "your.db.host";
[JsonProperty("Port")]
public int Port { get; set; } = 3306;
[JsonProperty("Username")]
public string Username { get; set; } = "moonlight_user";
[JsonProperty("Password")]
public string Password { get; set; } = "s3cr3t";
[JsonProperty("Database")]
public string Database { get; set; } = "moonlight_db";
}
public class MailServerData
{
[JsonProperty("Host")] public string Host { get; set; } = "your.email.host";
[JsonProperty("Port")] public int Port { get; set; } = 465;
[JsonProperty("Email")] public string Email { get; set; } = "noreply@your.email.host";
[JsonProperty("Password")] public string Password { get; set; } = "s3cr3t";
[JsonProperty("UseSsl")] public bool UseSsl { get; set; } = true;
[JsonProperty("SenderName")]
[Description("This will be shown as the system emails sender name in apps like gmail")]
public string SenderName { get; set; } = "Moonlight System";
}
}

View file

@ -1,85 +0,0 @@
using Microsoft.EntityFrameworkCore;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Services;
using Moonlight.Features.Community.Entities;
using Moonlight.Features.Servers.Entities;
using Moonlight.Features.ServiceManagement.Entities;
using Moonlight.Features.StoreSystem.Entities;
using Moonlight.Features.Theming.Entities;
using Moonlight.Features.Ticketing.Entities;
namespace Moonlight.Core.Database;
public class DataContext : DbContext
{
private readonly ConfigService<ConfigV1> ConfigService;
public DbSet<User> Users { get; set; }
// Store
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Service> Services { get; set; }
public DbSet<ServiceShare> ServiceShares { get; set; }
public DbSet<GiftCode> GiftCodes { get; set; }
public DbSet<GiftCodeUse> GiftCodeUses { get; set; }
public DbSet<Coupon> Coupons { get; set; }
public DbSet<CouponUse> CouponUses { get; set; }
// Community
public DbSet<Post> Posts { get; set; }
public DbSet<PostComment> PostComments { get; set; }
public DbSet<PostLike> PostLikes { get; set; }
public DbSet<WordFilter> WordFilters { get; set; }
// Tickets
public DbSet<Ticket> Tickets { get; set; }
public DbSet<TicketMessage> TicketMessages { get; set; }
// Themes
public DbSet<Theme> Themes { get; set; }
// Servers
public DbSet<Server> Servers { get; set; }
public DbSet<ServerAllocation> ServerAllocations { get; set; }
public DbSet<ServerImage> ServerImages { get; set; }
public DbSet<ServerNode> ServerNodes { get; set; }
public DbSet<ServerVariable> ServerVariables { get; set; }
public DbSet<ServerDockerImage> ServerDockerImages { get; set; }
public DbSet<ServerImageVariable> ServerImageVariables { get; set; }
public DbSet<ServerSchedule> ServerSchedules { get; set; }
public DataContext(ConfigService<ConfigV1> configService)
{
ConfigService = configService;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var config = ConfigService.Get().Database;
if (config.UseSqlite)
optionsBuilder.UseSqlite($"Data Source={config.SqlitePath}");
else
{
var connectionString = $"host={config.Host};" +
$"port={config.Port};" +
$"database={config.Database};" +
$"uid={config.Username};" +
$"pwd={config.Password}";
optionsBuilder.UseMySql(
connectionString,
ServerVersion.AutoDetect(connectionString),
builder => builder.EnableRetryOnFailure(5)
);
}
}
}
}

View file

@ -1,28 +0,0 @@
using Moonlight.Features.StoreSystem.Entities;
namespace Moonlight.Core.Database.Entities;
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string? Avatar { get; set; } = null;
public string? TotpKey { get; set; } = null;
// Store
public double Balance { get; set; }
public List<Transaction> Transactions { get; set; } = new();
public List<CouponUse> CouponUses { get; set; } = new();
public List<GiftCodeUse> GiftCodeUses { get; set; } = new();
// Meta data
public string Flags { get; set; } = "";
public int Permissions { get; set; } = 0;
// Timestamps
public DateTime TokenValidTimestamp { get; set; } = DateTime.UtcNow.AddMinutes(-10);
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -1,68 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231013200303_AddedUser")]
partial class AddedUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,43 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Username = table.Column<string>(type: "TEXT", nullable: false),
Email = table.Column<string>(type: "TEXT", nullable: false),
Password = table.Column<string>(type: "TEXT", nullable: false),
Avatar = table.Column<string>(type: "TEXT", nullable: true),
TotpKey = table.Column<string>(type: "TEXT", nullable: true),
Flags = table.Column<string>(type: "TEXT", nullable: false),
Permissions = table.Column<int>(type: "INTEGER", nullable: false),
TokenValidTimestamp = table.Column<DateTime>(type: "TEXT", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
}
}
}

View file

@ -1,342 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231017075519_AddStoreModels")]
partial class AddStoreModels
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId");
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,245 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddStoreModels : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Categories",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
Slug = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Categories", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Coupons",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Code = table.Column<string>(type: "TEXT", nullable: false),
Percent = table.Column<int>(type: "INTEGER", nullable: false),
Amount = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Coupons", x => x.Id);
});
migrationBuilder.CreateTable(
name: "GiftCodes",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Code = table.Column<string>(type: "TEXT", nullable: false),
Value = table.Column<double>(type: "REAL", nullable: false),
Amount = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GiftCodes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CategoryId = table.Column<int>(type: "INTEGER", nullable: true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
Slug = table.Column<string>(type: "TEXT", nullable: false),
Price = table.Column<double>(type: "REAL", nullable: false),
Stock = table.Column<int>(type: "INTEGER", nullable: false),
MaxPerUser = table.Column<int>(type: "INTEGER", nullable: false),
Duration = table.Column<int>(type: "INTEGER", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
ConfigJson = table.Column<string>(type: "TEXT", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
table.ForeignKey(
name: "FK_Products_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "CouponUses",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CouponId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CouponUses", x => x.Id);
table.ForeignKey(
name: "FK_CouponUses_Coupons_CouponId",
column: x => x.CouponId,
principalTable: "Coupons",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GiftCodeUses",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
GiftCodeId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GiftCodeUses", x => x.Id);
table.ForeignKey(
name: "FK_GiftCodeUses_GiftCodes_GiftCodeId",
column: x => x.GiftCodeId,
principalTable: "GiftCodes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Services",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Nickname = table.Column<string>(type: "TEXT", nullable: true),
Suspended = table.Column<bool>(type: "INTEGER", nullable: false),
ProductId = table.Column<int>(type: "INTEGER", nullable: false),
ConfigJsonOverride = table.Column<string>(type: "TEXT", nullable: true),
OwnerId = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
RenewAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Services", x => x.Id);
table.ForeignKey(
name: "FK_Services_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Services_Users_OwnerId",
column: x => x.OwnerId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ServiceShares",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
ServiceId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServiceShares", x => x.Id);
table.ForeignKey(
name: "FK_ServiceShares_Services_ServiceId",
column: x => x.ServiceId,
principalTable: "Services",
principalColumn: "Id");
table.ForeignKey(
name: "FK_ServiceShares_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_CouponUses_CouponId",
table: "CouponUses",
column: "CouponId");
migrationBuilder.CreateIndex(
name: "IX_GiftCodeUses_GiftCodeId",
table: "GiftCodeUses",
column: "GiftCodeId");
migrationBuilder.CreateIndex(
name: "IX_Products_CategoryId",
table: "Products",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_Services_OwnerId",
table: "Services",
column: "OwnerId");
migrationBuilder.CreateIndex(
name: "IX_Services_ProductId",
table: "Services",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_ServiceShares_ServiceId",
table: "ServiceShares",
column: "ServiceId");
migrationBuilder.CreateIndex(
name: "IX_ServiceShares_UserId",
table: "ServiceShares",
column: "UserId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CouponUses");
migrationBuilder.DropTable(
name: "GiftCodeUses");
migrationBuilder.DropTable(
name: "ServiceShares");
migrationBuilder.DropTable(
name: "Coupons");
migrationBuilder.DropTable(
name: "GiftCodes");
migrationBuilder.DropTable(
name: "Services");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Categories");
}
}
}

View file

@ -1,372 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231018203522_AddedUserStoreData")]
partial class AddedUserStoreData
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,130 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedUserStoreData : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Products_Categories_CategoryId",
table: "Products");
migrationBuilder.AddColumn<double>(
name: "Balance",
table: "Users",
type: "REAL",
nullable: false,
defaultValue: 0.0);
migrationBuilder.AlterColumn<int>(
name: "CategoryId",
table: "Products",
type: "INTEGER",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "INTEGER",
oldNullable: true);
migrationBuilder.AddColumn<int>(
name: "UserId",
table: "GiftCodeUses",
type: "INTEGER",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "UserId",
table: "CouponUses",
type: "INTEGER",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_GiftCodeUses_UserId",
table: "GiftCodeUses",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_CouponUses_UserId",
table: "CouponUses",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_CouponUses_Users_UserId",
table: "CouponUses",
column: "UserId",
principalTable: "Users",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_GiftCodeUses_Users_UserId",
table: "GiftCodeUses",
column: "UserId",
principalTable: "Users",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Products_Categories_CategoryId",
table: "Products",
column: "CategoryId",
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CouponUses_Users_UserId",
table: "CouponUses");
migrationBuilder.DropForeignKey(
name: "FK_GiftCodeUses_Users_UserId",
table: "GiftCodeUses");
migrationBuilder.DropForeignKey(
name: "FK_Products_Categories_CategoryId",
table: "Products");
migrationBuilder.DropIndex(
name: "IX_GiftCodeUses_UserId",
table: "GiftCodeUses");
migrationBuilder.DropIndex(
name: "IX_CouponUses_UserId",
table: "CouponUses");
migrationBuilder.DropColumn(
name: "Balance",
table: "Users");
migrationBuilder.DropColumn(
name: "UserId",
table: "GiftCodeUses");
migrationBuilder.DropColumn(
name: "UserId",
table: "CouponUses");
migrationBuilder.AlterColumn<int>(
name: "CategoryId",
table: "Products",
type: "INTEGER",
nullable: true,
oldClrType: typeof(int),
oldType: "INTEGER");
migrationBuilder.AddForeignKey(
name: "FK_Products_Categories_CategoryId",
table: "Products",
column: "CategoryId",
principalTable: "Categories",
principalColumn: "Id");
}
}
}

View file

@ -1,404 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231018204737_AddedTransactions")]
partial class AddedTransactions
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,46 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedTransactions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Transaction",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Price = table.Column<double>(type: "REAL", nullable: false),
Text = table.Column<string>(type: "TEXT", nullable: false),
UserId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Transaction", x => x.Id);
table.ForeignKey(
name: "FK_Transaction_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_Transaction_UserId",
table: "Transaction",
column: "UserId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Transaction");
}
}
}

View file

@ -1,540 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231027105412_AddPostsModels")]
partial class AddPostsModels
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Posts");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("PostId");
b.ToTable("PostComments");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("UserId");
b.ToTable("PostLikes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Comments")
.HasForeignKey("PostId");
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Likes")
.HasForeignKey("PostId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Navigation("Comments");
b.Navigation("Likes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,131 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddPostsModels : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Posts",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Title = table.Column<string>(type: "TEXT", nullable: false),
Content = table.Column<string>(type: "TEXT", nullable: false),
AuthorId = table.Column<int>(type: "INTEGER", nullable: false),
Type = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Posts", x => x.Id);
table.ForeignKey(
name: "FK_Posts_Users_AuthorId",
column: x => x.AuthorId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PostComments",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Content = table.Column<string>(type: "TEXT", nullable: false),
AuthorId = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
PostId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PostComments", x => x.Id);
table.ForeignKey(
name: "FK_PostComments_Posts_PostId",
column: x => x.PostId,
principalTable: "Posts",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PostComments_Users_AuthorId",
column: x => x.AuthorId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PostLikes",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
PostId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PostLikes", x => x.Id);
table.ForeignKey(
name: "FK_PostLikes_Posts_PostId",
column: x => x.PostId,
principalTable: "Posts",
principalColumn: "Id");
table.ForeignKey(
name: "FK_PostLikes_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_PostComments_AuthorId",
table: "PostComments",
column: "AuthorId");
migrationBuilder.CreateIndex(
name: "IX_PostComments_PostId",
table: "PostComments",
column: "PostId");
migrationBuilder.CreateIndex(
name: "IX_PostLikes_PostId",
table: "PostLikes",
column: "PostId");
migrationBuilder.CreateIndex(
name: "IX_PostLikes_UserId",
table: "PostLikes",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Posts_AuthorId",
table: "Posts",
column: "AuthorId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PostComments");
migrationBuilder.DropTable(
name: "PostLikes");
migrationBuilder.DropTable(
name: "Posts");
}
}
}

View file

@ -1,555 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231028214520_AddedWordFilter")]
partial class AddedWordFilter
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Posts");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("PostId");
b.ToTable("PostComments");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("UserId");
b.ToTable("PostLikes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.WordFilter", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Filter")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("WordFilters");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Comments")
.HasForeignKey("PostId");
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Likes")
.HasForeignKey("PostId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Navigation("Comments");
b.Navigation("Likes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,34 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedWordFilter : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "WordFilters",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Filter = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_WordFilters", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "WordFilters");
}
}
}

View file

@ -1,666 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231101161843_AddedTicketModels")]
partial class AddedTicketModels
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Posts");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("PostId");
b.ToTable("PostComments");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("UserId");
b.ToTable("PostLikes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.WordFilter", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Filter")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("WordFilters");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int>("CreatorId")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("Open")
.HasColumnType("INTEGER");
b.Property<int>("Priority")
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<string>("Tries")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CreatorId");
b.HasIndex("ServiceId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Attachment")
.HasColumnType("TEXT");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<bool>("IsSupport")
.HasColumnType("INTEGER");
b.Property<int?>("SenderId")
.HasColumnType("INTEGER");
b.Property<int?>("TicketId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SenderId");
b.HasIndex("TicketId");
b.ToTable("TicketMessages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Comments")
.HasForeignKey("PostId");
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Likes")
.HasForeignKey("PostId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", "Service")
.WithMany()
.HasForeignKey("ServiceId");
b.Navigation("Creator");
b.Navigation("Service");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Sender")
.WithMany()
.HasForeignKey("SenderId");
b.HasOne("Moonlight.Core.Database.Entities.Tickets.Ticket", null)
.WithMany("Messages")
.HasForeignKey("TicketId");
b.Navigation("Sender");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Navigation("Comments");
b.Navigation("Likes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,104 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedTicketModels : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Tickets",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CreatorId = table.Column<int>(type: "INTEGER", nullable: false),
Name = table.Column<string>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
Tries = table.Column<string>(type: "TEXT", nullable: false),
Priority = table.Column<int>(type: "INTEGER", nullable: false),
Open = table.Column<bool>(type: "INTEGER", nullable: false),
ServiceId = table.Column<int>(type: "INTEGER", nullable: true),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Tickets", x => x.Id);
table.ForeignKey(
name: "FK_Tickets_Services_ServiceId",
column: x => x.ServiceId,
principalTable: "Services",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Tickets_Users_CreatorId",
column: x => x.CreatorId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "TicketMessages",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SenderId = table.Column<int>(type: "INTEGER", nullable: true),
IsSupport = table.Column<bool>(type: "INTEGER", nullable: false),
Content = table.Column<string>(type: "TEXT", nullable: false),
Attachment = table.Column<string>(type: "TEXT", nullable: true),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
TicketId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketMessages", x => x.Id);
table.ForeignKey(
name: "FK_TicketMessages_Tickets_TicketId",
column: x => x.TicketId,
principalTable: "Tickets",
principalColumn: "Id");
table.ForeignKey(
name: "FK_TicketMessages_Users_SenderId",
column: x => x.SenderId,
principalTable: "Users",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_TicketMessages_SenderId",
table: "TicketMessages",
column: "SenderId");
migrationBuilder.CreateIndex(
name: "IX_TicketMessages_TicketId",
table: "TicketMessages",
column: "TicketId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_CreatorId",
table: "Tickets",
column: "CreatorId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_ServiceId",
table: "Tickets",
column: "ServiceId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "TicketMessages");
migrationBuilder.DropTable(
name: "Tickets");
}
}
}

View file

@ -1,698 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20231222100225_AddThemeModel")]
partial class AddThemeModel
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Posts");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("PostId");
b.ToTable("PostComments");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("UserId");
b.ToTable("PostLikes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.WordFilter", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Filter")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("WordFilters");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Theme", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CssUrl")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DonateUrl")
.HasColumnType("TEXT");
b.Property<bool>("Enabled")
.HasColumnType("INTEGER");
b.Property<string>("JsUrl")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Themes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int>("CreatorId")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("Open")
.HasColumnType("INTEGER");
b.Property<int>("Priority")
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<string>("Tries")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CreatorId");
b.HasIndex("ServiceId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Attachment")
.HasColumnType("TEXT");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<bool>("IsSupport")
.HasColumnType("INTEGER");
b.Property<int?>("SenderId")
.HasColumnType("INTEGER");
b.Property<int?>("TicketId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SenderId");
b.HasIndex("TicketId");
b.ToTable("TicketMessages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Comments")
.HasForeignKey("PostId");
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Likes")
.HasForeignKey("PostId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", "Service")
.WithMany()
.HasForeignKey("ServiceId");
b.Navigation("Creator");
b.Navigation("Service");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Sender")
.WithMany()
.HasForeignKey("SenderId");
b.HasOne("Moonlight.Core.Database.Entities.Tickets.Ticket", null)
.WithMany("Messages")
.HasForeignKey("TicketId");
b.Navigation("Sender");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Navigation("Comments");
b.Navigation("Likes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,39 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddThemeModel : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Themes",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Author = table.Column<string>(type: "TEXT", nullable: false),
DonateUrl = table.Column<string>(type: "TEXT", nullable: true),
CssUrl = table.Column<string>(type: "TEXT", nullable: false),
JsUrl = table.Column<string>(type: "TEXT", nullable: true),
Enabled = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Themes", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Themes");
}
}
}

View file

@ -1,701 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Moonlight.Core.Database;
using Moonlight.Core.Database;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20240119090835_AddedTransactionDate")]
partial class AddedTransactionDate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Posts");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AuthorId")
.HasColumnType("INTEGER");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("PostId");
b.ToTable("PostComments");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int?>("PostId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PostId");
b.HasIndex("UserId");
b.ToTable("PostLikes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.WordFilter", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Filter")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("WordFilters");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Coupon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Percent")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Coupons");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CouponId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CouponId");
b.HasIndex("UserId");
b.ToTable("CouponUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Amount")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Value")
.HasColumnType("REAL");
b.HasKey("Id");
b.ToTable("GiftCodes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("GiftCodeId")
.HasColumnType("INTEGER");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("GiftCodeId");
b.HasIndex("UserId");
b.ToTable("GiftCodeUses");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("CategoryId")
.HasColumnType("INTEGER");
b.Property<string>("ConfigJson")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Duration")
.HasColumnType("INTEGER");
b.Property<int>("MaxPerUser")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Slug")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Stock")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.ToTable("Products");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ConfigJsonOverride")
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Nickname")
.HasColumnType("TEXT");
b.Property<int>("OwnerId")
.HasColumnType("INTEGER");
b.Property<int>("ProductId")
.HasColumnType("INTEGER");
b.Property<DateTime>("RenewAt")
.HasColumnType("TEXT");
b.Property<bool>("Suspended")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("OwnerId");
b.HasIndex("ProductId");
b.ToTable("Services");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<int>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("UserId");
b.ToTable("ServiceShares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<double>("Price")
.HasColumnType("REAL");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Transaction");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Theme", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CssUrl")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DonateUrl")
.HasColumnType("TEXT");
b.Property<bool>("Enabled")
.HasColumnType("INTEGER");
b.Property<string>("JsUrl")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Themes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<int>("CreatorId")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("Open")
.HasColumnType("INTEGER");
b.Property<int>("Priority")
.HasColumnType("INTEGER");
b.Property<int?>("ServiceId")
.HasColumnType("INTEGER");
b.Property<string>("Tries")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CreatorId");
b.HasIndex("ServiceId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Attachment")
.HasColumnType("TEXT");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<bool>("IsSupport")
.HasColumnType("INTEGER");
b.Property<int?>("SenderId")
.HasColumnType("INTEGER");
b.Property<int?>("TicketId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SenderId");
b.HasIndex("TicketId");
b.ToTable("TicketMessages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Avatar")
.HasColumnType("TEXT");
b.Property<double>("Balance")
.HasColumnType("REAL");
b.Property<DateTime>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Flags")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Permissions")
.HasColumnType("INTEGER");
b.Property<DateTime>("TokenValidTimestamp")
.HasColumnType("TEXT");
b.Property<string>("TotpKey")
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostComment", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Comments")
.HasForeignKey("PostId");
b.Navigation("Author");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.PostLike", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Community.Post", null)
.WithMany("Likes")
.HasForeignKey("PostId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.CouponUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Coupon", "Coupon")
.WithMany()
.HasForeignKey("CouponId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("CouponUses")
.HasForeignKey("UserId");
b.Navigation("Coupon");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.GiftCodeUse", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.GiftCode", "GiftCode")
.WithMany()
.HasForeignKey("GiftCodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("GiftCodeUses")
.HasForeignKey("UserId");
b.Navigation("GiftCode");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Product", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Product", "Product")
.WithMany()
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Owner");
b.Navigation("Product");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.ServiceShare", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", null)
.WithMany("Shares")
.HasForeignKey("ServiceId");
b.HasOne("Moonlight.Core.Database.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Transaction", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", null)
.WithMany("Transactions")
.HasForeignKey("UserId");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Moonlight.Core.Database.Entities.Store.Service", "Service")
.WithMany()
.HasForeignKey("ServiceId");
b.Navigation("Creator");
b.Navigation("Service");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.TicketMessage", b =>
{
b.HasOne("Moonlight.Core.Database.Entities.User", "Sender")
.WithMany()
.HasForeignKey("SenderId");
b.HasOne("Moonlight.Core.Database.Entities.Tickets.Ticket", null)
.WithMany("Messages")
.HasForeignKey("TicketId");
b.Navigation("Sender");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Community.Post", b =>
{
b.Navigation("Comments");
b.Navigation("Likes");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Store.Service", b =>
{
b.Navigation("Shares");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.Tickets.Ticket", b =>
{
b.Navigation("Messages");
});
modelBuilder.Entity("Moonlight.Core.Database.Entities.User", b =>
{
b.Navigation("CouponUses");
b.Navigation("GiftCodeUses");
b.Navigation("Transactions");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -1,30 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedTransactionDate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "CreatedAt",
table: "Transaction",
type: "TEXT",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CreatedAt",
table: "Transaction");
}
}
}

View file

@ -1,266 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedServerModels : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ServerImages",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
AllocationsNeeded = table.Column<int>(type: "INTEGER", nullable: false),
StartupCommand = table.Column<string>(type: "TEXT", nullable: false),
StopCommand = table.Column<string>(type: "TEXT", nullable: false),
OnlineDetection = table.Column<string>(type: "TEXT", nullable: false),
ParseConfigurations = table.Column<string>(type: "TEXT", nullable: false),
InstallDockerImage = table.Column<string>(type: "TEXT", nullable: false),
InstallShell = table.Column<string>(type: "TEXT", nullable: false),
InstallScript = table.Column<string>(type: "TEXT", nullable: false),
Author = table.Column<string>(type: "TEXT", nullable: false),
DonateUrl = table.Column<string>(type: "TEXT", nullable: true),
UpdateUrl = table.Column<string>(type: "TEXT", nullable: true),
DefaultDockerImageIndex = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerImages", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ServerImageVariables",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Key = table.Column<string>(type: "TEXT", nullable: false),
DefaultValue = table.Column<string>(type: "TEXT", nullable: false),
DisplayName = table.Column<string>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
AllowUserToEdit = table.Column<bool>(type: "INTEGER", nullable: false),
AllowUserToView = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerImageVariables", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ServerNodes",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Fqdn = table.Column<string>(type: "TEXT", nullable: false),
UseSsl = table.Column<bool>(type: "INTEGER", nullable: false),
Token = table.Column<string>(type: "TEXT", nullable: false),
HttpPort = table.Column<int>(type: "INTEGER", nullable: false),
FtpPort = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerNodes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ServerDockerImages",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
DisplayName = table.Column<string>(type: "TEXT", nullable: false),
AutoPull = table.Column<bool>(type: "INTEGER", nullable: false),
ServerImageId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerDockerImages", x => x.Id);
table.ForeignKey(
name: "FK_ServerDockerImages_ServerImages_ServerImageId",
column: x => x.ServerImageId,
principalTable: "ServerImages",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ServerAllocations",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
IpAddress = table.Column<string>(type: "TEXT", nullable: false),
Port = table.Column<int>(type: "INTEGER", nullable: false),
ServerId = table.Column<int>(type: "INTEGER", nullable: true),
ServerNodeId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerAllocations", x => x.Id);
table.ForeignKey(
name: "FK_ServerAllocations_ServerNodes_ServerNodeId",
column: x => x.ServerNodeId,
principalTable: "ServerNodes",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "Servers",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ServiceId = table.Column<int>(type: "INTEGER", nullable: false),
Cpu = table.Column<int>(type: "INTEGER", nullable: false),
Memory = table.Column<int>(type: "INTEGER", nullable: false),
Disk = table.Column<int>(type: "INTEGER", nullable: false),
ImageId = table.Column<int>(type: "INTEGER", nullable: false),
DockerImageIndex = table.Column<int>(type: "INTEGER", nullable: false),
OverrideStartupCommand = table.Column<string>(type: "TEXT", nullable: true),
NodeId = table.Column<int>(type: "INTEGER", nullable: false),
MainAllocationId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Servers", x => x.Id);
table.ForeignKey(
name: "FK_Servers_ServerAllocations_MainAllocationId",
column: x => x.MainAllocationId,
principalTable: "ServerAllocations",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_ServerImages_ImageId",
column: x => x.ImageId,
principalTable: "ServerImages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_ServerNodes_NodeId",
column: x => x.NodeId,
principalTable: "ServerNodes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Servers_Services_ServiceId",
column: x => x.ServiceId,
principalTable: "Services",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ServerVariables",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Key = table.Column<string>(type: "TEXT", nullable: false),
Value = table.Column<string>(type: "TEXT", nullable: false),
ServerId = table.Column<int>(type: "INTEGER", 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");
});
migrationBuilder.CreateIndex(
name: "IX_ServerAllocations_ServerId",
table: "ServerAllocations",
column: "ServerId");
migrationBuilder.CreateIndex(
name: "IX_ServerAllocations_ServerNodeId",
table: "ServerAllocations",
column: "ServerNodeId");
migrationBuilder.CreateIndex(
name: "IX_ServerDockerImages_ServerImageId",
table: "ServerDockerImages",
column: "ServerImageId");
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_ServiceId",
table: "Servers",
column: "ServiceId");
migrationBuilder.CreateIndex(
name: "IX_ServerVariables_ServerId",
table: "ServerVariables",
column: "ServerId");
migrationBuilder.AddForeignKey(
name: "FK_ServerAllocations_Servers_ServerId",
table: "ServerAllocations",
column: "ServerId",
principalTable: "Servers",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ServerAllocations_ServerNodes_ServerNodeId",
table: "ServerAllocations");
migrationBuilder.DropForeignKey(
name: "FK_Servers_ServerNodes_NodeId",
table: "Servers");
migrationBuilder.DropForeignKey(
name: "FK_ServerAllocations_Servers_ServerId",
table: "ServerAllocations");
migrationBuilder.DropTable(
name: "ServerDockerImages");
migrationBuilder.DropTable(
name: "ServerImageVariables");
migrationBuilder.DropTable(
name: "ServerVariables");
migrationBuilder.DropTable(
name: "ServerNodes");
migrationBuilder.DropTable(
name: "Servers");
migrationBuilder.DropTable(
name: "ServerAllocations");
migrationBuilder.DropTable(
name: "ServerImages");
}
}
}

View file

@ -1,48 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class FixedMissingPropertyInServerImage : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ServerImageId",
table: "ServerImageVariables",
type: "INTEGER",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_ServerImageVariables_ServerImageId",
table: "ServerImageVariables",
column: "ServerImageId");
migrationBuilder.AddForeignKey(
name: "FK_ServerImageVariables_ServerImages_ServerImageId",
table: "ServerImageVariables",
column: "ServerImageId",
principalTable: "ServerImages",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ServerImageVariables_ServerImages_ServerImageId",
table: "ServerImageVariables");
migrationBuilder.DropIndex(
name: "IX_ServerImageVariables_ServerImageId",
table: "ServerImageVariables");
migrationBuilder.DropColumn(
name: "ServerImageId",
table: "ServerImageVariables");
}
}
}

View file

@ -1,29 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedAllowUserToChangeDockerImage : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "AllowUserToChangeDockerImage",
table: "ServerImages",
type: "INTEGER",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AllowUserToChangeDockerImage",
table: "ServerImages");
}
}
}

View file

@ -1,51 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.Core.Database.Migrations
{
/// <inheritdoc />
public partial class AddedServerSchedules : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ServerSchedules",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Cron = table.Column<string>(type: "TEXT", nullable: false),
ActionType = table.Column<int>(type: "INTEGER", nullable: false),
ActionData = table.Column<string>(type: "TEXT", nullable: false),
LastRunAt = table.Column<DateTime>(type: "TEXT", nullable: false),
WasLastRunAutomatic = table.Column<bool>(type: "INTEGER", nullable: false),
ServerId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ServerSchedules", x => x.Id);
table.ForeignKey(
name: "FK_ServerSchedules_Servers_ServerId",
column: x => x.ServerId,
principalTable: "Servers",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_ServerSchedules_ServerId",
table: "ServerSchedules",
column: "ServerId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ServerSchedules");
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Event.Args;
public class MailVerificationEventArgs
{
public User User { get; set; }
public string Jwt { get; set; }
}

View file

@ -1,9 +0,0 @@
using Moonlight.Features.Ticketing.Entities;
namespace Moonlight.Core.Event.Args;
public class TicketMessageEventArgs
{
public Ticket Ticket { get; set; }
public TicketMessage TicketMessage { get; set; }
}

View file

@ -1,10 +0,0 @@
using Moonlight.Core.Database.Entities;
using Moonlight.Features.StoreSystem.Entities;
namespace Moonlight.Core.Event.Args;
public class TransactionCreatedEventArgs
{
public Transaction Transaction { get; set; }
public User User { get; set; }
}

View file

@ -1,27 +0,0 @@
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Event.Args;
using Moonlight.Features.Community.Entities;
using Moonlight.Features.ServiceManagement.Entities;
using Moonlight.Features.Ticketing.Entities;
namespace Moonlight.Core.Event;
public class Events
{
public static EventHandler<User> OnUserRegistered;
public static EventHandler<User> OnUserPasswordChanged;
public static EventHandler<User> OnUserTotpSet;
public static EventHandler<MailVerificationEventArgs> OnUserMailVerify;
public static EventHandler<Service> OnServiceOrdered;
public static EventHandler<TransactionCreatedEventArgs> OnTransactionCreated;
public static EventHandler<Post> OnPostCreated;
public static EventHandler<Post> OnPostUpdated;
public static EventHandler<Post> OnPostDeleted;
public static EventHandler<Post> OnPostLiked;
public static EventHandler<PostComment> OnPostCommentCreated;
public static EventHandler<PostComment> OnPostCommentDeleted;
public static EventHandler<Ticket> OnTicketCreated;
public static EventHandler<TicketMessageEventArgs> OnTicketMessage;
public static EventHandler<Ticket> OnTicketUpdated;
public static EventHandler OnMoonlightRestart;
}

View file

@ -1,20 +0,0 @@
using Moonlight.Core.Models.Enums;
namespace Moonlight.Core.Extensions.Attributes;
public class RequirePermissionAttribute : Attribute
{
public int PermissionInteger = 0;
public RequirePermissionAttribute(){}
public RequirePermissionAttribute(int perms)
{
PermissionInteger = perms;
}
public RequirePermissionAttribute(Permission permission)
{
PermissionInteger = (int)permission;
}
}

View file

@ -1,22 +0,0 @@
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Newtonsoft.Json;
namespace Moonlight.Core.Extensions;
public static class ConfigServiceExtensions
{
public static string GetDiagnosticJson(this ConfigService<ConfigV1> configService)
{
var jsonUnsafe = JsonConvert.SerializeObject(configService.Get());
var configUnsafe = JsonConvert.DeserializeObject<ConfigV1>(jsonUnsafe)!;
// Remote sensitive data
configUnsafe.Database.Password =
string.IsNullOrEmpty(configUnsafe.Database.Password) ? "IS EMPTY" : "IS NOT EMPTY";
configUnsafe.Security.Token = string.IsNullOrEmpty(configUnsafe.Security.Token) ? "IS EMPTY" : "IS NOT EMPTY";
configUnsafe.MailServer.Password =string.IsNullOrEmpty(configUnsafe.MailServer.Password) ? "IS EMPTY" : "IS NOT EMPTY";
return JsonConvert.SerializeObject(configUnsafe, Formatting.Indented);
}
}

View file

@ -1,37 +0,0 @@
namespace Moonlight.Core.Extensions;
public static class EventHandlerExtensions
{
public static async Task InvokeAsync(this EventHandler handler)
{
var tasks = handler
.GetInvocationList()
.Select(x => new Task(() => x.DynamicInvoke(null, null)))
.ToArray();
foreach (var task in tasks)
{
task.Start();
}
await Task.WhenAll(tasks);
}
public static async Task InvokeAsync<T>(this EventHandler<T>? handler, T? data = default(T))
{
if(handler == null)
return;
var tasks = handler
.GetInvocationList()
.Select(x => new Task(() => x.DynamicInvoke(null, data)))
.ToArray();
foreach (var task in tasks)
{
task.Start();
}
await Task.WhenAll(tasks);
}
}

View file

@ -1,26 +0,0 @@
using System.IO.Compression;
using System.Text;
namespace Moonlight.Core.Extensions;
public static class ZipArchiveExtension
{
public static async Task AddFromText(this ZipArchive archive, string entryName, string content)
{
using var memoryStream = new MemoryStream();
await memoryStream.WriteAsync(Encoding.UTF8.GetBytes(content));
await memoryStream.FlushAsync();
await archive.AddFromStream(entryName, memoryStream);
}
public static async Task AddFromStream(this ZipArchive archive, string entryName, Stream dataStream)
{
var entry = archive.CreateEntry(entryName, CompressionLevel.Fastest);
await using var stream = entry.Open();
dataStream.Position = 0;
await dataStream.CopyToAsync(stream);
await stream.FlushAsync();
}
}

View file

@ -1,65 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using MoonCore.Helpers;
using Moonlight.Features.Theming.Services;
namespace Moonlight.Core.Http.Controllers.Api;
[ApiController]
[Route("api/assetproxy")]
public class AssetProxyController : Controller
{
private readonly ThemeService ThemeService;
public AssetProxyController(ThemeService themeService)
{
ThemeService = themeService;
}
[HttpGet("theme/{id}/js")]
public async Task<ActionResult> GetThemeJs(int id)
{
var enabledThemes = await ThemeService.GetEnabled();
var selectedTheme = enabledThemes.FirstOrDefault(x => x.Id == id);
if (selectedTheme == null)
return NotFound();
try
{
using var httpClient = new HttpClient();
var content = await httpClient.GetByteArrayAsync(selectedTheme.JsUrl);
return File(content, "text/javascript");
}
catch (Exception e)
{
Logger.Warn($"Error proxying js for theme {id}");
Logger.Warn(e);
return Problem();
}
}
[HttpGet("theme/{id}/css")]
public async Task<ActionResult> GetThemeCss(int id)
{
var enabledThemes = await ThemeService.GetEnabled();
var selectedTheme = enabledThemes.FirstOrDefault(x => x.Id == id);
if (selectedTheme == null)
return NotFound();
try
{
using var httpClient = new HttpClient();
var content = await httpClient.GetByteArrayAsync(selectedTheme.CssUrl);
return File(content, "text/css");
}
catch (Exception e)
{
Logger.Warn($"Error proxying css for theme {id}");
Logger.Warn(e);
return Problem();
}
}
}

View file

@ -1,65 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using MoonCore.Abstractions;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Models.Enums;
using Moonlight.Core.Services;
using Moonlight.Core.Services.Utils;
namespace Moonlight.Core.Http.Controllers.Api.Auth;
[ApiController]
[Route("api/auth/reset")]
public class ResetController : Controller
{
private readonly Repository<User> UserRepository;
private readonly IdentityService IdentityService;
private readonly JwtService JwtService;
public ResetController(Repository<User> userRepository, IdentityService identityService, JwtService jwtService)
{
UserRepository = userRepository;
IdentityService = identityService;
JwtService = jwtService;
}
[HttpGet]
public async Task<ActionResult> Get([FromQuery] string token)
{
// Validate token
if (!await JwtService.Validate(token))
return Redirect("/password-reset");
var data = await JwtService.Decode(token);
if (!data.ContainsKey("accountToReset"))
return Redirect("/password-reset");
var userId = int.Parse(data["accountToReset"]);
var user = UserRepository
.Get()
.FirstOrDefault(x => x.Id == userId);
// User may have been deleted, so we check here
if (user == null)
return Redirect("/password-reset");
// In order to allow the user to get access to the change password screen
// we need to authenticate him so we can read his flags.
// That's why we are creating a session here
var sessionToken = await IdentityService.GenerateToken(user);
// Authenticate the current identity service instance in order to
// get access to the flags field.
await IdentityService.Authenticate(sessionToken);
IdentityService.Flags[UserFlag.PasswordPending] = true;
await IdentityService.SaveFlags();
// Make the user login so he can reach the change password screen
Response.Cookies.Append("token", sessionToken);
return Redirect("/");
}
}

View file

@ -1,51 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using MoonCore.Helpers;
using Moonlight.Core.Models.Enums;
using Moonlight.Core.Services;
using Moonlight.Core.Services.Utils;
namespace Moonlight.Core.Http.Controllers.Api.Auth;
[ApiController]
[Route("api/auth/verify")]
public class VerifyController : Controller
{
private readonly IdentityService IdentityService;
private readonly JwtService JwtService;
public VerifyController(IdentityService identityService, JwtService jwtService)
{
IdentityService = identityService;
JwtService = jwtService;
}
[HttpGet]
public async Task<ActionResult> Get([FromQuery] string token)
{
await IdentityService.Authenticate(Request);
if (!IdentityService.IsSignedIn)
return Redirect("/login");
if (!await JwtService.Validate(token))
return Redirect("/login");
var data = await JwtService.Decode(token);
if (!data.ContainsKey("mailToVerify"))
return Redirect("/login");
var mailToVerify = data["mailToVerify"];
if (mailToVerify != IdentityService.CurrentUser.Email)
{
Logger.Warn($"User {IdentityService.CurrentUser.Email} tried to mail verify {mailToVerify} via verify api endpoint", "security");
return Redirect("/login");
}
IdentityService.Flags[UserFlag.MailVerified] = true;
await IdentityService.SaveFlags();
return Redirect("/");
}
}

View file

@ -1,37 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using MoonCore.Helpers;
using Moonlight.Core.Services;
namespace Moonlight.Core.Http.Controllers.Api;
[ApiController]
[Route("api/bucket")]
public class BucketController : Controller
{
private readonly BucketService BucketService;
public BucketController(BucketService bucketService)
{
BucketService = bucketService;
}
[HttpGet("{bucket}/{file}")]
public async Task<ActionResult> Get([FromRoute] string bucket, [FromRoute] string file) // TODO: Implement auth
{
if (bucket.Contains("..") || file.Contains(".."))
{
Logger.Warn($"Detected path transversal attack ({Request.HttpContext.Connection.RemoteIpAddress}).", "security");
return NotFound();
}
try
{
var stream = await BucketService.Pull(bucket, file);
return File(stream, MimeTypes.GetMimeType(file));
}
catch (FileNotFoundException)
{
return NotFound();
}
}
}

View file

@ -1,50 +0,0 @@
using Moonlight.Core.Models.Enums;
namespace Moonlight.Core.Models.Abstractions;
public class FlagStorage
{
private readonly List<string> FlagList;
public UserFlag[] Flags => FlagList
.Select(x => Enum.Parse(typeof(UserFlag), x))
.Select(x => (UserFlag)x)
.ToArray();
public string[] RawFlags => FlagList.ToArray();
public string RawFlagString => string.Join(";", FlagList);
public bool this[UserFlag flag]
{
get => Flags.Contains(flag);
set => Set(flag.ToString(), value);
}
public bool this[string flagName]
{
get => FlagList.Contains(flagName);
set => Set(flagName, value);
}
public FlagStorage(string flagString)
{
FlagList = flagString
.Split(";")
.Where(x => !string.IsNullOrEmpty(x))
.ToList();
}
public void Set(string flagName, bool shouldAdd)
{
if (shouldAdd)
{
if(!FlagList.Contains(flagName))
FlagList.Add(flagName);
}
else
{
if (FlagList.Contains(flagName))
FlagList.Remove(flagName);
}
}
}

View file

@ -1,34 +0,0 @@
using Moonlight.Core.Models.Enums;
namespace Moonlight.Core.Models.Abstractions;
public class PermissionStorage
{
public readonly int PermissionInteger;
public PermissionStorage(int permissionInteger)
{
PermissionInteger = permissionInteger;
}
public Permission[] Permissions => GetPermissions();
public Permission[] GetPermissions()
{
return GetAllPermissions()
.Where(x => (int)x <= PermissionInteger)
.ToArray();
}
public static Permission[] GetAllPermissions()
{
return Enum.GetValues<Permission>();
}
public static Permission GetFromInteger(int id)
{
return GetAllPermissions().First(x => (int)x == id);
}
public bool this[Permission permission] => Permissions.Contains(permission);
}

View file

@ -1,12 +0,0 @@
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Models.Abstractions;
public class Session
{
public string Ip { get; set; } = "N/A";
public string Url { get; set; } = "N/A";
public User? User { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; // To remove inactive sessions
}

View file

@ -1,8 +0,0 @@
namespace Moonlight.Core.Models.Abstractions;
public class Subscriber
{
public string Id { get; set; }
public object Action { get; set; }
public object Handle { get; set; }
}

View file

@ -1,18 +0,0 @@
namespace Moonlight.Core.Models.Enums;
public enum Permission
{
Default = 0,
AdminMenu = 999,
AdminOverview = 1000,
AdminUsers = 1001,
AdminSessions = 1002,
AdminUsersEdit = 1003,
AdminTickets = 1004,
AdminCommunity = 1030,
AdminServices = 1050,
AdminServers = 1060,
AdminStore = 1900,
AdminViewExceptions = 1999,
AdminRoot = 2000
}

View file

@ -1,8 +0,0 @@
namespace Moonlight.Core.Models.Enums;
public enum UserFlag
{
MailVerified,
PasswordPending,
TotpEnabled
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Admin.Users;
public class UpdateUserForm
{
[Required(ErrorMessage = "You need to enter a username")]
[MinLength(7, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
[RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers")]
public string Username { get; set; } = "";
[Required(ErrorMessage = "You need to enter a email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; } = "";
}

View file

@ -1,11 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Admin.Users;
public class UpdateUserPasswordForm
{
[Required(ErrorMessage = "You need to specify a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string Password { get; set; } = "";
}

View file

@ -1,13 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class LoginForm
{
[Required(ErrorMessage = "You need to provide an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; }
[Required(ErrorMessage = "You need to provide a password")]
public string Password { get; set; }
}

View file

@ -1,26 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class RegisterForm
{
[Required(ErrorMessage = "You need to provide an username")]
[MinLength(7, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
[RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers and should not start with a number")]
public string Username { get; set; }
[Required(ErrorMessage = "You need to provide an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; }
[Required(ErrorMessage = "You need to provide a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string Password { get; set; }
[Required(ErrorMessage = "You need to provide a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string RepeatedPassword { get; set; }
}

View file

@ -1,10 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class ResetPasswordForm
{
[Required(ErrorMessage = "You need to specify an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; } = "";
}

View file

@ -1,9 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class TwoFactorCodeForm
{
[Required(ErrorMessage = "You need to enter a two factor code")]
public string Code { get; set; } = "";
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class UpdateAccountForm
{
[Required(ErrorMessage = "You need to provide an username")]
[MinLength(7, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
[RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers")]
public string Username { get; set; }
[Required(ErrorMessage = "You need to provide an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; }
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Core.Models.Forms.Auth;
public class UpdateAccountPasswordForm
{
[Required(ErrorMessage = "You need to specify a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string Password { get; set; } = "";
[Required(ErrorMessage = "You need to repeat your new password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string RepeatedPassword { get; set; } = "";
}

View file

@ -1,6 +0,0 @@
namespace Moonlight.Core.Models.Templates;
public class MailVerify
{
public string Url { get; set; } = "";
}

View file

@ -1,6 +0,0 @@
namespace Moonlight.Core.Models.Templates;
public class ResetPassword
{
public string Url { get; set; } = "";
}

View file

@ -1,16 +0,0 @@
using Moonlight.Features.ServiceManagement.Models.Abstractions;
namespace Moonlight.Core.Plugins.Contexts;
public class PluginContext
{
public IServiceCollection Services { get; set; }
public IServiceProvider Provider { get; set; }
public IServiceScope Scope { get; set; }
public WebApplicationBuilder WebApplicationBuilder { get; set; }
public WebApplication WebApplication { get; set; }
public List<Action> PreInitTasks = new();
public List<Action> PostInitTasks = new();
public Action<ServiceViewContext>? BuildUserServiceView { get; set; } = null;
public Action<ServiceViewContext>? BuildAdminServiceView { get; set; } = null;
}

View file

@ -1,10 +0,0 @@
using Moonlight.Core.Plugins.Contexts;
namespace Moonlight.Core.Plugins;
public abstract class MoonlightPlugin
{
public PluginContext Context { get; set; }
public abstract Task Enable();
public abstract Task Disable();
}

View file

@ -1,43 +0,0 @@
using Microsoft.EntityFrameworkCore;
using MoonCore.Abstractions;
using MoonCore.Attributes;
using Moonlight.Core.Database;
namespace Moonlight.Core.Repositories;
[Scoped]
public class GenericRepository<TEntity> : Repository<TEntity> where TEntity : class
{
private readonly DataContext DataContext;
private readonly DbSet<TEntity> DbSet;
public GenericRepository(DataContext dbContext)
{
DataContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
DbSet = DataContext.Set<TEntity>();
}
public override DbSet<TEntity> Get()
{
return DbSet;
}
public override TEntity Add(TEntity entity)
{
var x = DbSet.Add(entity);
DataContext.SaveChanges();
return x.Entity;
}
public override void Update(TEntity entity)
{
DbSet.Update(entity);
DataContext.SaveChanges();
}
public override void Delete(TEntity entity)
{
DbSet.Remove(entity);
DataContext.SaveChanges();
}
}

View file

@ -1,59 +0,0 @@
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Event;
using Moonlight.Core.Event.Args;
using Moonlight.Features.ServiceManagement.Entities;
using BackgroundService = MoonCore.Abstractions.BackgroundService;
namespace Moonlight.Core.Services.Background;
public class AutoMailSendService : BackgroundService // This service is responsible for sending mails automatically
{
private readonly MailService MailService;
public AutoMailSendService(MailService mailService)
{
MailService = mailService;
}
public override Task Run()
{
Events.OnUserRegistered += OnUserRegistered;
Events.OnServiceOrdered += OnServiceOrdered;
Events.OnTransactionCreated += OnTransactionCreated;
return Task.CompletedTask;
}
private async void OnTransactionCreated(object? sender, TransactionCreatedEventArgs eventArgs)
{
await MailService.Send(
eventArgs.User,
"New transaction",
"transactionCreated",
eventArgs.Transaction,
eventArgs.User
);
}
private async void OnServiceOrdered(object? _, Service service)
{
await MailService.Send(
service.Owner,
"New product ordered",
"serviceOrdered",
service,
service.Product,
service.Owner
);
}
private async void OnUserRegistered(object? _, User user)
{
await MailService.Send(
user,
$"Welcome {user.Username}",
"welcome",
user
);
}
}

View file

@ -1,86 +0,0 @@
using MoonCore.Attributes;
using MoonCore.Helpers;
namespace Moonlight.Core.Services;
[Singleton]
public class BucketService
{
private readonly string BasePath;
public string[] Buckets => GetBuckets();
public BucketService()
{
// This is used to create the buckets folder in the persistent storage of helio
BasePath = PathBuilder.Dir("storage", "buckets");
Directory.CreateDirectory(BasePath);
}
public string[] GetBuckets()
{
return Directory
.GetDirectories(BasePath)
.Select(x =>
x.Replace(BasePath, "").TrimEnd('/')
)
.ToArray();
}
public Task EnsureBucket(string name) // To ensure a specific bucket has been created, call this function
{
Directory.CreateDirectory(PathBuilder.Dir(BasePath, name));
return Task.CompletedTask;
}
public async Task<string> Store(string bucket, Stream dataStream, string fileName)
{
await EnsureBucket(bucket); // Ensure the bucket actually exists
// Create a safe to file name to store the file
var extension = Path.GetExtension(fileName);
var finalFileName = Path.GetRandomFileName() + extension;
var finalFilePath = PathBuilder.File(BasePath, bucket, finalFileName);
// Copy the file from the remote stream to the bucket
var fs = File.Create(finalFilePath);
await dataStream.CopyToAsync(fs);
await fs.FlushAsync();
fs.Close();
// Return the generated file name to save it in the db or smth
return finalFileName;
}
public Task<Stream> Pull(string bucket, string file)
{
var filePath = PathBuilder.File(BasePath, bucket, file);
if (File.Exists(filePath))
{
var stream = File.Open(filePath, FileMode.Open);
return Task.FromResult<Stream>(stream);
}
else
throw new FileNotFoundException();
}
public Task Delete(string bucket, string file, bool ignoreNotFound = false)
{
var filePath = PathBuilder.File(BasePath, bucket, file);
if (File.Exists(filePath))
{
File.Delete(filePath);
return Task.CompletedTask;
}
// This section will only be reached if the file does not exist
if (!ignoreNotFound)
throw new FileNotFoundException();
return Task.CompletedTask;
}
}

View file

@ -1,39 +0,0 @@
using Microsoft.JSInterop;
using MoonCore.Attributes;
using MoonCore.Helpers;
namespace Moonlight.Core.Services;
[Scoped]
public class HotKeyService : IAsyncDisposable
{
private readonly IJSRuntime JsRuntime;
public SmartEventHandler<string> HotKeyPressed { get; set; } = new();
public HotKeyService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task Initialize()
{
var reference = DotNetObjectReference.Create(this);
await JsRuntime.InvokeVoidAsync("moonlight.hotkeys.registerListener", reference);
}
[JSInvokable]
public async void OnHotkeyPressed(string hotKey)
{
await HotKeyPressed.Invoke(hotKey);
}
public async ValueTask DisposeAsync()
{
try
{
await JsRuntime.InvokeVoidAsync("moonlight.keyListener.unregisterListener");
}
catch (Exception) { /* ignored */}
}
}

View file

@ -1,189 +0,0 @@
using Microsoft.EntityFrameworkCore;
using MoonCore.Abstractions;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using MoonCore.Helpers;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.Models.Enums;
using Moonlight.Core.Services.Utils;
using Moonlight.Features.StoreSystem.Entities;
using OtpNet;
namespace Moonlight.Core.Services;
// This service allows you to reauthenticate, login and force login
// It does also contain the permission system accessor for the current user
[Scoped]
public class IdentityService
{
private readonly Repository<User> UserRepository;
private readonly JwtService JwtService;
private string Token;
public User? CurrentUserNullable { get; private set; }
public User CurrentUser => CurrentUserNullable!;
public bool IsSignedIn => CurrentUserNullable != null;
public FlagStorage Flags { get; private set; } = new("");
public PermissionStorage Permissions { get; private set; } = new(-1);
public Transaction[] Transactions => GetTransactions().Result; // TODO: make more efficient
public EventHandler OnAuthenticationStateChanged { get; set; }
public IdentityService(Repository<User> userRepository,
JwtService jwtService)
{
UserRepository = userRepository;
JwtService = jwtService;
}
// Transactions
public Task<Transaction[]> GetTransactions()
{
if (CurrentUserNullable == null)
return Task.FromResult(Array.Empty<Transaction>());
var user = UserRepository
.Get()
.Include(x => x.Transactions)
.First(x => x.Id == CurrentUserNullable.Id);
return Task.FromResult(user.Transactions.ToArray());
}
// Authentication
public async Task Authenticate() // Reauthenticate
{
// Save the last id (or -1 if not set) so we can track a change
var lastUserId = CurrentUserNullable == null ? -1 : CurrentUserNullable.Id;
// Reset
CurrentUserNullable = null;
await ValidateToken();
// Get current user id to compare against the last one
var currentUserId = CurrentUserNullable == null ? -1 : CurrentUserNullable.Id;
if (lastUserId != currentUserId) // State changed, lets notify all event listeners
OnAuthenticationStateChanged?.Invoke(this, null!);
}
private async Task ValidateToken() // Read and validate token
{
if (string.IsNullOrEmpty(Token))
return;
if (!await JwtService.Validate(Token, "User"))
return;
var data = await JwtService.Decode(Token);
if (!data.ContainsKey("userId"))
return;
var userId = int.Parse(data["userId"]);
var user = UserRepository
.Get()
.FirstOrDefault(x => x.Id == userId);
if (user == null)
return;
if (!data.ContainsKey("issuedAt"))
return;
var issuedAt = long.Parse(data["issuedAt"]);
var issuedAtDateTime = DateTimeOffset.FromUnixTimeSeconds(issuedAt).DateTime;
// If the valid time is newer then when the token was issued, the token is not longer valid
if (user.TokenValidTimestamp > issuedAtDateTime)
return;
CurrentUserNullable = user;
if (CurrentUserNullable == null) // If the current user is null, stop loading additional data
return;
Flags = new(CurrentUser.Flags);
Permissions = new(CurrentUser.Permissions);
}
public async Task<string> Login(string email, string password, string? code = null)
{
var user = UserRepository
.Get()
.FirstOrDefault(x => x.Email == email);
if (user == null)
throw new DisplayException("A user with these credential combination was not found");
if (!HashHelper.Verify(password, user.Password))
throw new DisplayException("A user with these credential combination was not found");
var flags = new FlagStorage(user.Flags); // Construct FlagStorage to check for 2fa
if (!flags[UserFlag.TotpEnabled]) // No 2fa found on this user so were done here
return await GenerateToken(user);
// If we reach this point, 2fa is enabled so we need to continue validating
if (string.IsNullOrEmpty(code)) // This will show an additional 2fa login field
throw new ArgumentNullException(nameof(code), "2FA code missing");
if (user.TotpKey == null) // Hopefully we will never fulfill this check ;)
throw new DisplayException("2FA key is missing. Please contact the support to fix your account");
// Calculate server side code
var totp = new Totp(Base32Encoding.ToBytes(user.TotpKey));
var codeServerSide = totp.ComputeTotp();
if (codeServerSide == code)
return await GenerateToken(user);
throw new DisplayException("Invalid 2fa code entered");
}
public async Task<string> GenerateToken(User user)
{
var token = await JwtService.Create(data =>
{
data.Add("userId", user.Id.ToString());
data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
}, "User", TimeSpan.FromDays(10));
return token;
}
public Task SaveFlags()
{
// Prevent saving flags for an empty user
if (!IsSignedIn)
return Task.CompletedTask;
// Save the new flag string
CurrentUser.Flags = Flags.RawFlagString;
UserRepository.Update(CurrentUser);
return Task.CompletedTask;
}
// Helpers and overloads
public async Task
Authenticate(HttpRequest request) // Overload for api controllers to authenticate a user like the normal panel
{
if (request.Cookies.ContainsKey("token"))
{
var token = request.Cookies["token"];
await Authenticate(token!);
}
}
public async Task Authenticate(string token) // Overload to set token and reauth
{
Token = token;
await Authenticate();
}
}

View file

@ -1,110 +0,0 @@
using MailKit.Net.Smtp;
using MimeKit;
using MoonCore.Attributes;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Services;
[Singleton]
public class MailService
{
private readonly ConfigService<ConfigV1> ConfigService;
private readonly string BasePath;
public MailService(ConfigService<ConfigV1> configService)
{
ConfigService = configService;
BasePath = PathBuilder.Dir("storage", "mail");
Directory.CreateDirectory(BasePath);
}
public async Task Send(User user, string title, string templateName, params object[] models)
{
var config = ConfigService.Get().MailServer;
try
{
// Build mail message
var message = new MimeMessage();
message.From.Add(new MailboxAddress(
config.SenderName,
config.Email
));
message.To.Add(new MailboxAddress(
$"{user.Username}",
user.Email
));
message.Subject = Formatter.ProcessTemplating(title, models);
var body = new BodyBuilder()
{
HtmlBody = await ParseTemplate(templateName, models)
};
message.Body = body.ToMessageBody();
// The actual sending will not be done in the mail thread to prevent long loading times
Task.Run(async () =>
{
using var smtpClient = new SmtpClient();
try
{
Logger.Debug($"Sending {templateName} mail to {user.Email}");
Logger.Debug($"Body: {body.HtmlBody}");
await smtpClient.ConnectAsync(config.Host, config.Port, config.UseSsl);
await smtpClient.AuthenticateAsync(config.Email, config.Password);
await smtpClient.SendAsync(message);
await smtpClient.DisconnectAsync(true);
}
catch (Exception e)
{
Logger.Warn("An unexpected error occured while connecting and transferring mail to mailserver");
Logger.Warn(e);
}
});
}
catch (FileNotFoundException)
{
// ignored as we log it anyways in the parse template function
}
catch (Exception e)
{
Logger.Warn("Unhandled error occured during sending mail:");
Logger.Warn(e);
}
}
private async Task<string> ParseTemplate(string templateName, params object[] models)
{
if (!File.Exists(PathBuilder.File(BasePath, templateName + ".html")))
{
Logger.Warn($"Mail template '{templateName}' is missing. Skipping sending mail");
throw new FileNotFoundException();
}
var text = await File.ReadAllTextAsync(
PathBuilder.File(BasePath, templateName + ".html")
);
// For details how the templating works, check out the explanation of the ProcessTemplating in the Formatter class
text = Formatter.ProcessTemplating(text, models);
return text;
}
// Helpers
public async Task Send(IEnumerable<User> users, string title, string templateName, params object[] models)
{
foreach (var user in users)
await Send(user, title, templateName, models);
}
}

View file

@ -1,100 +0,0 @@
using System.IO.Compression;
using MoonCore.Abstractions;
using MoonCore.Attributes;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Moonlight.Core.Event;
using Moonlight.Core.Extensions;
using Moonlight.Features.Servers.Entities;
using Moonlight.Features.Theming.Services;
using Newtonsoft.Json;
namespace Moonlight.Core.Services;
[Singleton]
public class MoonlightService // This service can be used to perform strictly panel specific actions
{
private readonly ConfigService<ConfigV1> ConfigService;
private readonly IServiceProvider ServiceProvider;
public WebApplication Application { get; set; } // Do NOT modify using a plugin
public string LogPath { get; set; } // Do NOT modify using a plugin
public ThemeService Theme => ServiceProvider.GetRequiredService<ThemeService>();
public MoonlightService(ConfigService<ConfigV1> configService, IServiceProvider serviceProvider)
{
ConfigService = configService;
ServiceProvider = serviceProvider;
}
public async Task Restart()
{
Logger.Info("Restarting moonlight");
// Notify all users that this instance will restart
await Events.OnMoonlightRestart.InvokeAsync();
await Task.Delay(TimeSpan.FromSeconds(3));
await Application.StopAsync();
}
public async Task<byte[]> GenerateDiagnoseReport()
{
var scope = ServiceProvider.CreateScope();
// Prepare zip file
var memoryStream = new MemoryStream();
var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);
// Add current log
// We need to open the file this way because we need to specify the access and share mode directly
// in order to read from a file which is currently written to
var fs = File.Open(LogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var sr = new StreamReader(fs);
var log = await sr.ReadToEndAsync();
sr.Close();
fs.Close();
await zip.AddFromText("log.txt", log);
// Add node config
var nodeRepo = scope.ServiceProvider.GetRequiredService<Repository<ServerNode>>();
var nodes = nodeRepo.Get().ToArray();
foreach (var node in nodes)
{
// Remove sensitive data
node.Token = string.IsNullOrEmpty(node.Token) ? "IS EMPTY" : "IS NOT EMPTY";
}
var nodesJson = JsonConvert.SerializeObject(nodes, Formatting.Indented);
await zip.AddFromText("nodes.json", nodesJson);
// Add config
var configJson = ConfigService.GetDiagnosticJson();
await zip.AddFromText("config.json", configJson);
// Make a list of plugins
var pluginService = scope.ServiceProvider.GetRequiredService<PluginService>();
var plugins = await pluginService.GetLoadedPlugins();
var pluginList = "Installed plugins:\n";
foreach (var plugin in plugins)
{
var assembly = plugin.GetType().Assembly;
pluginList += $"{assembly.FullName} ({assembly.Location})\n";
}
await zip.AddFromText("pluginList.txt", pluginList);
// Add more information here
// Finalize file
zip.Dispose();
memoryStream.Close();
var data = memoryStream.ToArray();
return data;
}
}

View file

@ -1,145 +0,0 @@
using System.Reflection;
using MoonCore.Helpers;
using Moonlight.Core.Plugins;
using Moonlight.Core.Plugins.Contexts;
using Moonlight.Features.ServiceManagement.Models.Abstractions;
namespace Moonlight.Core.Services;
public class PluginService
{
private readonly List<MoonlightPlugin> Plugins = new();
public async Task Load(WebApplicationBuilder webApplicationBuilder)
{
var path = PathBuilder.Dir("storage", "plugins");
Directory.CreateDirectory(path);
var files = FindFiles(path)
.Where(x => x.EndsWith(".dll"))
.ToArray();
foreach (var file in files)
{
try
{
var assembly = Assembly.LoadFile(PathBuilder.File(Directory.GetCurrentDirectory(), file));
int plugins = 0;
foreach (var type in assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(MoonlightPlugin)))
{
try
{
var plugin = (Activator.CreateInstance(type) as MoonlightPlugin)!;
// Create environment
plugin.Context = new PluginContext()
{
Services = webApplicationBuilder.Services,
WebApplicationBuilder = webApplicationBuilder
};
try
{
await plugin.Enable();
// After here we can treat the plugin as successfully loaded
plugins++;
Plugins.Add(plugin);
}
catch (Exception e)
{
Logger.Fatal($"Unhandled exception while enabling plugin '{type.Name}'");
Logger.Fatal(e);
}
}
catch (Exception e)
{
Logger.Fatal($"Failed to create plugin environment for '{type.Name}'");
Logger.Fatal(e);
}
}
}
if(plugins == 0) // If 0, we can assume that it was a library dll
Logger.Info($"Loaded {file} as a library");
else
Logger.Info($"Loaded {plugins} plugin(s) from {file}");
}
catch (Exception e)
{
Logger.Fatal($"Unable to load assembly from file '{file}'");
Logger.Fatal(e);
}
}
Logger.Info($"Loaded {Plugins.Count} plugin(s)");
}
public Task<MoonlightPlugin[]> GetLoadedPlugins() => Task.FromResult(Plugins.ToArray());
public async Task RunPreInit()
{
foreach (var plugin in Plugins)
{
Logger.Info($"Running pre init tasks for {plugin.GetType().Name}");
foreach (var preInitTask in plugin.Context.PreInitTasks)
await Task.Run(preInitTask);
}
}
public async Task RunPrePost(WebApplication webApplication)
{
foreach (var plugin in Plugins)
{
// Pass through the dependency injection
var scope = webApplication.Services.CreateScope();
plugin.Context.Provider = scope.ServiceProvider;
plugin.Context.Scope = scope;
plugin.Context.WebApplication = webApplication;
Logger.Info($"Running post init tasks for {plugin.GetType().Name}");
foreach (var postInitTask in plugin.Context.PostInitTasks)
await Task.Run(postInitTask);
}
}
public Task BuildUserServiceView(ServiceViewContext context)
{
foreach (var plugin in Plugins)
{
plugin.Context.BuildUserServiceView?.Invoke(context);
}
return Task.CompletedTask;
}
public Task BuildAdminServiceView(ServiceViewContext context)
{
foreach (var plugin in Plugins)
{
plugin.Context.BuildAdminServiceView?.Invoke(context);
}
return Task.CompletedTask;
}
private string[] FindFiles(string dir)
{
var result = new List<string>();
foreach (var file in Directory.GetFiles(dir))
result.Add(file);
foreach (var directory in Directory.GetDirectories(dir))
{
result.AddRange(FindFiles(directory));
}
return result.ToArray();
}
}

View file

@ -1,40 +0,0 @@
using MoonCore.Attributes;
using Moonlight.Core.Models.Abstractions;
namespace Moonlight.Core.Services;
[Singleton]
public class SessionService
{
private readonly List<Session> AllSessions = new();
public Session[] Sessions => GetSessions();
public Task Register(Session session)
{
lock (AllSessions)
{
AllSessions.Add(session);
}
return Task.CompletedTask;
}
public Task Unregister(Session session)
{
lock (AllSessions)
{
AllSessions.Remove(session);
}
return Task.CompletedTask;
}
public Session[] GetSessions()
{
lock (AllSessions)
{
return AllSessions.ToArray();
}
}
}

View file

@ -1,134 +0,0 @@
using MoonCore.Abstractions;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Event;
using Moonlight.Core.Extensions;
using Moonlight.Core.Models.Abstractions;
using Moonlight.Core.Models.Enums;
using Moonlight.Core.Models.Templates;
using Moonlight.Core.Services.Utils;
using OtpNet;
namespace Moonlight.Core.Services.Users;
[Scoped]
public class UserAuthService
{
private readonly Repository<User> UserRepository;
private readonly JwtService JwtService;
private readonly ConfigService<ConfigV1> ConfigService;
private readonly MailService MailService;
public UserAuthService(
Repository<User> userRepository,
JwtService jwtService,
ConfigService<ConfigV1> configService,
MailService mailService)
{
UserRepository = userRepository;
JwtService = jwtService;
ConfigService = configService;
MailService = mailService;
}
public async Task<User> Register(string username, string email, string password)
{
// Event though we have form validation i want to
// ensure that at least these basic formatting things are done
email = email.ToLower().Trim();
username = username.ToLower().Trim();
// Prevent duplication or username and/or email
if (UserRepository.Get().Any(x => x.Email == email))
throw new DisplayException("A user with that email does already exist");
if (UserRepository.Get().Any(x => x.Username == username))
throw new DisplayException("A user with that username does already exist");
var user = new User()
{
Username = username,
Email = email,
Password = HashHelper.HashToString(password)
};
var result = UserRepository.Add(user);
await Events.OnUserRegistered.InvokeAsync(result);
return result;
}
public async Task ChangePassword(User user, string newPassword)
{
user.Password = HashHelper.HashToString(newPassword);
user.TokenValidTimestamp = DateTime.UtcNow;
UserRepository.Update(user);
await Events.OnUserPasswordChanged.InvokeAsync(user);
}
public Task SeedTotp(User user)
{
var key = Base32Encoding.ToString(KeyGeneration.GenerateRandomKey(20));
user.TotpKey = key;
UserRepository.Update(user);
return Task.CompletedTask;
}
public async Task SetTotp(User user, bool state)
{
// Access to flags without identity service
var flags = new FlagStorage(user.Flags);
flags[UserFlag.TotpEnabled] = state;
user.Flags = flags.RawFlagString;
if (!state)
user.TotpKey = null;
UserRepository.Update(user);
await Events.OnUserTotpSet.InvokeAsync(user);
}
// Mails
public async Task SendVerification(User user)
{
var jwt = await JwtService.Create(data =>
{
data.Add("mailToVerify", user.Email);
}, "EmailVerification", TimeSpan.FromMinutes(10));
await MailService.Send(user, "Verify your account", "verifyMail", user, new MailVerify()
{
Url = ConfigService.Get().AppUrl + "/api/auth/verify?token=" + jwt
});
}
public async Task SendResetPassword(string email)
{
var user = UserRepository
.Get()
.FirstOrDefault(x => x.Email == email);
if (user == null)
throw new DisplayException("An account with that email was not found");
var jwt = await JwtService.Create(data =>
{
data.Add("accountToReset", user.Id.ToString());
}, "PasswordReset", TimeSpan.FromHours(1));
await MailService.Send(user, "Password reset for your account", "passwordReset", user, new ResetPassword()
{
Url = ConfigService.Get().AppUrl + "/api/auth/reset?token=" + jwt
});
}
}

View file

@ -1,173 +0,0 @@
using Microsoft.EntityFrameworkCore;
using MoonCore.Abstractions;
using MoonCore.Attributes;
using Moonlight.Core.Database.Entities;
using Moonlight.Features.Community.Entities;
using Moonlight.Features.Community.Services;
using Moonlight.Features.ServiceManagement.Entities;
using Moonlight.Features.ServiceManagement.Services;
using Moonlight.Features.StoreSystem.Entities;
using Moonlight.Features.Ticketing.Entities;
namespace Moonlight.Core.Services.Users;
[Scoped]
public class UserDeleteService
{
private readonly Repository<Service> ServiceRepository;
private readonly Repository<ServiceShare> ServiceShareRepository;
private readonly Repository<Post> PostRepository;
private readonly Repository<User> UserRepository;
private readonly Repository<Transaction> TransactionRepository;
private readonly Repository<CouponUse> CouponUseRepository;
private readonly Repository<GiftCodeUse> GiftCodeUseRepository;
private readonly Repository<Ticket> TicketRepository;
private readonly Repository<TicketMessage> TicketMessageRepository;
private readonly ServiceService ServiceService;
private readonly PostService PostService;
public UserDeleteService(
Repository<Service> serviceRepository,
ServiceService serviceService,
PostService postService,
Repository<Post> postRepository,
Repository<User> userRepository,
Repository<GiftCodeUse> giftCodeUseRepository,
Repository<CouponUse> couponUseRepository,
Repository<Transaction> transactionRepository,
Repository<Ticket> ticketRepository,
Repository<TicketMessage> ticketMessageRepository,
Repository<ServiceShare> serviceShareRepository)
{
ServiceRepository = serviceRepository;
ServiceService = serviceService;
PostService = postService;
PostRepository = postRepository;
UserRepository = userRepository;
GiftCodeUseRepository = giftCodeUseRepository;
CouponUseRepository = couponUseRepository;
TransactionRepository = transactionRepository;
TicketRepository = ticketRepository;
TicketMessageRepository = ticketMessageRepository;
ServiceShareRepository = serviceShareRepository;
}
public async Task Perform(User user)
{
// Community
// - Posts
foreach (var post in PostRepository.Get().ToArray())
{
await PostService.Delete(post);
}
// - Comments
var posts = PostRepository
.Get()
.Where(x => x.Comments.Any(y => y.Author.Id == user.Id))
.ToArray();
foreach (var post in posts)
{
var comments = PostRepository
.Get()
.Include(x => x.Comments)
.ThenInclude(x => x.Author)
.First(x => x.Id == post.Id)
.Comments
.Where(x => x.Author.Id == user.Id)
.ToArray();
foreach (var comment in comments)
await PostService.DeleteComment(post, comment);
}
// Services
foreach (var service in ServiceRepository.Get().Where(x => x.Owner.Id == user.Id).ToArray())
{
await ServiceService.Admin.Delete(service);
}
// Service shares
var shares = ServiceShareRepository
.Get()
.Where(x => x.User.Id == user.Id)
.ToArray();
foreach (var share in shares)
{
ServiceShareRepository.Delete(share);
}
// Transactions - Coupons - Gift codes
var userWithDetails = UserRepository
.Get()
.Include(x => x.Transactions)
.Include(x => x.CouponUses)
.Include(x => x.GiftCodeUses)
.First(x => x.Id == user.Id);
var giftCodeUses = userWithDetails.GiftCodeUses.ToArray();
var couponUses = userWithDetails.CouponUses.ToArray();
var transactions = userWithDetails.Transactions.ToArray();
userWithDetails.GiftCodeUses.Clear();
userWithDetails.CouponUses.Clear();
userWithDetails.Transactions.Clear();
UserRepository.Update(userWithDetails);
foreach (var giftCodeUse in giftCodeUses)
GiftCodeUseRepository.Delete(giftCodeUse);
foreach (var couponUse in couponUses)
CouponUseRepository.Delete(couponUse);
foreach (var transaction in transactions)
TransactionRepository.Delete(transaction);
// Tickets and ticket messages
// First we need to fetch every message this user has sent and delete it as admin accounts can have messages
// in tickets they dont own
var messagesFromUser = TicketMessageRepository
.Get()
.Where(x => x.Sender.Id == user.Id)
.ToArray();
foreach (var message in messagesFromUser)
{
TicketMessageRepository.Delete(message);
}
// Now we can only delete the tickets the user actually owns
var tickets = TicketRepository
.Get()
.Include(x => x.Messages)
.Where(x => x.Creator.Id == user.Id)
.ToArray();
foreach (var ticket in tickets)
{
var messages = ticket.Messages.ToArray(); // Cache message models
ticket.Messages.Clear();
TicketRepository.Update(ticket);
foreach (var ticketMessage in messages)
{
TicketMessageRepository.Delete(ticketMessage);
}
TicketRepository.Delete(ticket);
}
// User
// We need to use this in order to entity framework not crashing because of the previous deleted data
var userToDelete = UserRepository.Get().First(x => x.Id == user.Id);
UserRepository.Delete(userToDelete);
}
}

View file

@ -1,43 +0,0 @@
using MoonCore.Abstractions;
using MoonCore.Attributes;
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Services.Users;
[Scoped]
public class UserDetailsService
{
private readonly BucketService BucketService;
private readonly Repository<User> UserRepository;
public UserDetailsService(BucketService bucketService, Repository<User> userRepository)
{
BucketService = bucketService;
UserRepository = userRepository;
}
public async Task UpdateAvatar(User user, Stream stream, string fileName)
{
if (user.Avatar != null)
{
await BucketService.Delete("avatars", user.Avatar, true);
}
var file = await BucketService.Store("avatars", stream, fileName);
user.Avatar = file;
UserRepository.Update(user);
}
public async Task UpdateAvatar(User user) // Overload to reset avatar
{
if (user.Avatar != null)
{
await BucketService.Delete("avatars", user.Avatar, true);
}
user.Avatar = null;
UserRepository.Update(user);
}
}

View file

@ -1,47 +0,0 @@
using MoonCore.Abstractions;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Services.Users;
[Scoped]
public class UserService
{
private readonly Repository<User> UserRepository;
private readonly IServiceProvider ServiceProvider;
public UserAuthService Auth => ServiceProvider.GetRequiredService<UserAuthService>();
public UserDetailsService Details => ServiceProvider.GetRequiredService<UserDetailsService>();
public UserDeleteService Delete => ServiceProvider.GetRequiredService<UserDeleteService>();
public UserService(
Repository<User> userRepository,
IServiceProvider serviceProvider)
{
UserRepository = userRepository;
ServiceProvider = serviceProvider;
}
public Task Update(User user, string username, string email)
{
// Event though we have form validation i want to
// ensure that at least these basic formatting things are done
email = email.ToLower().Trim();
username = username.ToLower().Trim();
// Prevent duplication or username and/or email
if (UserRepository.Get().Any(x => x.Email == email && x.Id != user.Id))
throw new DisplayException("A user with that email does already exist");
if (UserRepository.Get().Any(x => x.Username == username && x.Id != user.Id))
throw new DisplayException("A user with that username does already exist");
user.Username = username;
user.Email = email;
UserRepository.Update(user);
return Task.CompletedTask;
}
}

View file

@ -1,38 +0,0 @@
using MoonCore.Attributes;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
namespace Moonlight.Core.Services.Utils;
[Scoped]
public class ConnectionService
{
private readonly IHttpContextAccessor ContextAccessor;
private readonly ConfigService<ConfigV1> ConfigService;
public ConnectionService(IHttpContextAccessor contextAccessor, ConfigService<ConfigV1> configService)
{
ContextAccessor = contextAccessor;
ConfigService = configService;
}
public Task<string> GetIpAddress()
{
if (ContextAccessor.HttpContext == null)
return Task.FromResult("N/A (Missing http context)");
var request = ContextAccessor.HttpContext.Request;
if (request.Headers.ContainsKey("X-Real-IP"))
{
if(ConfigService.Get().Security.EnableReverseProxyMode)
return Task.FromResult(request.Headers["X-Real-IP"].ToString());
Logger.Warn($"Detected an ip mask attempt by using a fake X-Real-IP header. Fake IP: {request.Headers["X-Real-IP"]}. Real IP: {ContextAccessor.HttpContext.Connection.RemoteIpAddress}");
return Task.FromResult(ContextAccessor.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "N/A (Remote IP missing)");
}
return Task.FromResult(ContextAccessor.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "N/A (Remote IP missing)");
}
}

View file

@ -1,123 +0,0 @@
using JWT.Algorithms;
using JWT.Builder;
using JWT.Exceptions;
using MoonCore.Attributes;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Newtonsoft.Json;
namespace Moonlight.Core.Services.Utils;
[Singleton]
public class JwtService
{
private readonly ConfigService<ConfigV1> ConfigService;
private readonly TimeSpan DefaultDuration = TimeSpan.FromDays(365 * 10);
public JwtService(ConfigService<ConfigV1> configService)
{
ConfigService = configService;
}
public Task<string> Create(Action<Dictionary<string, string>> data, string type, TimeSpan? validDuration = null)
{
var builder = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token)
.IssuedAt(DateTime.UtcNow)
.AddHeader("Type", type)
.ExpirationTime(DateTime.UtcNow.Add(validDuration ?? DefaultDuration))
.WithAlgorithm(new HMACSHA512Algorithm());
var dataDic = new Dictionary<string, string>();
data.Invoke(dataDic);
foreach (var entry in dataDic)
builder = builder.AddClaim(entry.Key, entry.Value);
var jwt = builder.Encode();
return Task.FromResult(jwt);
}
public Task<bool> Validate(string token, params string[] allowedJwtTypes)
{
try
{
// Without the body decode call the jwt validation would not work for some weird reason.
// It would not throw an error when the signature is invalid
_ = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token)
.WithAlgorithm(new HMACSHA512Algorithm())
.MustVerifySignature()
.Decode(token);
var headerJson = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token)
.WithAlgorithm(new HMACSHA512Algorithm())
.MustVerifySignature()
.DecodeHeader(token);
if (headerJson == null)
return Task.FromResult(false);
// Jwt type validation
if (allowedJwtTypes.Length == 0)
return Task.FromResult(true);
var headerData = JsonConvert.DeserializeObject<Dictionary<string, string>>(headerJson);
if (headerData == null) // => Invalid header
return Task.FromResult(false);
if (!headerData.ContainsKey("Type")) // => Invalid header, Type is missing
return Task.FromResult(false);
foreach (var name in allowedJwtTypes)
{
if (headerData["Type"] == name) // => Correct type found
return Task.FromResult(true);
}
// None found? Invalid type!
return Task.FromResult(false);
}
catch (SignatureVerificationException)
{
Logger.Warn($"A manipulated jwt has been found. Required jwt types: {string.Join(" ", allowedJwtTypes)} Jwt: {token}");
return Task.FromResult(false);
}
catch (Exception e)
{
Logger.Warn(e.Message);
return Task.FromResult(false);
}
}
public Task<Dictionary<string, string>> Decode(string token)
{
try
{
var json = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token)
.WithAlgorithm(new HMACSHA512Algorithm())
.MustVerifySignature()
.Decode(token);
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
return Task.FromResult(data)!;
}
catch (SignatureVerificationException)
{
return Task.FromResult(new Dictionary<string, string>());
}
catch (Exception e)
{
Logger.Warn("An unknown error occured while processing token");
Logger.Warn(e);
return Task.FromResult<Dictionary<string, string>>(null!);
}
}
}

View file

@ -1,33 +0,0 @@
<div class="d-flex flex-column flex-center text-center p-10">
<div class="card card-flush w-lg-650px py-5">
<div class="card-body py-15 py-lg-20">
<div class="mb-5">
<img src="/svg/nodata.svg" style="width: 10vh" alt="Not found illustration">
</div>
<h1 class="fw-bolder fs-2hx text-gray-900 mb-4">
The requested resource was not found
</h1>
<div class="fw-semibold fs-6 text-gray-500 mb-7">
<span class="fs-5">We were not able to find the requested resource. This can have following reasons</span>
<div class="mt-4 d-flex flex-column align-items-start">
<li class="d-flex align-items-center py-2">
<span class="bullet me-5"></span> The resource was deleted
</li>
<li class="d-flex align-items-center py-2">
<span class="bullet me-5"></span> You have no permission to access this resource
</li>
<li class="d-flex align-items-center py-2">
<span class="bullet me-5"></span> You may have entered invalid data
</li>
<li class="d-flex align-items-center py-2">
<span class="bullet me-5"></span> A unknown bug occured
</li>
<li class="d-flex align-items-center py-2">
<span class="bullet me-5"></span> An api was offline and not proper handled
</li>
</div>
</div>
</div>
</div>
</div>

View file

@ -1,16 +0,0 @@
<div class="w-100">
<div class="card-body">
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Restarting
</h1>
<div class="text-gray-400 fw-semibold fs-6">
The panel is restarting. This may take a moment
</div>
</div>
<div class="d-flex flex-stack">
<a href="javascript:location.reload()" class="btn btn-primary me-2 flex-shrink-0">Reconnect</a>
</div>
</div>
</div>

View file

@ -1,67 +0,0 @@
@using Moonlight.Core.Models.Forms
@using Moonlight.Core.Models.Enums
@using Moonlight.Core.Models.Forms.Auth
@using Moonlight.Core.Services
@using Moonlight.Core.Services.Users
@using MoonCore.Exceptions
@inject IdentityService IdentityService
@inject UserService UserService
<div class="w-100">
<div class="card-body">
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Change your password
</h1>
<div class="text-gray-400 fw-semibold fs-6">
You need to change your password in order to continue
</div>
</div>
<SmartForm Model="Form" OnValidSubmit="OnValidSubmit">
<div class="fv-row mb-7">
<input @bind="Form.Password" type="password" placeholder="Password" class="form-control form-control-solid">
</div>
<div class="fv-row mb-7">
<input @bind="Form.RepeatedPassword" type="password" placeholder="Repeat password" class="form-control form-control-solid">
</div>
<div class="d-flex flex-stack">
<button type="submit" class="btn btn-primary me-2 flex-shrink-0">Continue</button>
</div>
</SmartForm>
</div>
</div>
@code
{
private UpdateAccountPasswordForm Form = new();
private async Task OnValidSubmit()
{
if (Form.Password != Form.RepeatedPassword)
throw new DisplayException("The password do not match");
// Because of UserService.Auth.ChangePassword may logout the user before we can reset the flag
// we reset the flag before changing the password and if any error occurs we simple set it again
try
{
IdentityService.Flags[UserFlag.PasswordPending] = false;
await IdentityService.SaveFlags();
await UserService.Auth.ChangePassword(IdentityService.CurrentUser, Form.Password);
}
catch (Exception)
{
IdentityService.Flags[UserFlag.PasswordPending] = true;
await IdentityService.SaveFlags();
throw;
}
await IdentityService.Authenticate();
}
}

View file

@ -1,81 +0,0 @@
@page "/login"
@* Virtual route to trick blazor *@
@using Moonlight.Core.Models.Forms
@using Moonlight.Core.Models.Forms.Auth
@using Moonlight.Core.Services
@using MoonCoreUI.Services
@inject IdentityService IdentityService
@inject CookieService CookieService
@inject NavigationManager Navigation
<div class="w-100">
<div class="card-body">
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Sign In
</h1>
<div class="text-gray-400 fw-semibold fs-6">
Change me
</div>
</div>
<SmartForm Model="Form" OnValidSubmit="OnValidSubmit">
<div class="fv-row mb-8">
<input @bind="Form.Email" type="text" placeholder="Email" class="form-control form-control-solid">
</div>
<div class="fv-row mb-7">
<input @bind="Form.Password" type="password" placeholder="Password" class="form-control form-control-solid">
</div>
<div class="d-flex flex-stack flex-wrap gap-3 fs-base fw-semibold mb-10">
<a href="/password-reset" class="link-primary">
Forgot Password ?
</a>
<a href="/register" class="link-primary">
Need an account ?
</a>
</div>
<div class="d-flex flex-stack">
<button type="submit" class="btn btn-primary me-2 flex-shrink-0">Sign In</button>
<div class="d-flex align-items-center">
<div class="text-gray-400 fw-semibold fs-6 me-3 me-md-6">Or</div>
@* OAuth2 Providers here *@
</div>
</div>
</SmartForm>
</div>
</div>
@code
{
private LoginForm Form = new();
// 2FA
private bool Require2FA = false;
private string TwoFactorCode = "";
private async Task OnValidSubmit()
{
string token;
try
{
token = await IdentityService.Login(Form.Email, Form.Password, TwoFactorCode);
}
catch (ArgumentNullException) // IdentityService requires two factor code => show field
{
Require2FA = true;
await InvokeAsync(StateHasChanged);
return;
}
await CookieService.SetValue("token", token);
await IdentityService.Authenticate(token);
if (Navigation.Uri.EndsWith("/login"))
Navigation.NavigateTo("/");
}
}

View file

@ -1,45 +0,0 @@
@using Moonlight.Core.Services.Users
@using Moonlight.Core.Services
@inject UserService UserService
@inject IdentityService IdentityService
<div class="w-100">
<div class="card-body">
@if (HasBeenSend)
{
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Email verification sent
</h1>
<div class="text-gray-400 fw-semibold fs-6">
You should receive an email shortly. If you see no email in your inbox, look inside your spam folder
</div>
</div>
}
else
{
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Verify your email address
</h1>
<div class="text-gray-400 fw-semibold fs-6">
We will sent you an email to verify your account
</div>
</div>
<WButton OnClick="Send" Text="Send verification email" CssClasses="btn btn-primary me-2 flex-shrink-0" />
}
</div>
</div>
@code
{
private bool HasBeenSend = false;
private async Task Send()
{
await UserService.Auth.SendVerification(IdentityService.CurrentUser);
HasBeenSend = true;
await InvokeAsync(StateHasChanged);
}
}

View file

@ -1,56 +0,0 @@
@page "/password-reset"
@using Moonlight.Core.Models.Forms
@using Moonlight.Core.Models.Forms.Auth
@using Moonlight.Core.Services.Users
@inject UserService UserService
<div class="w-100">
<div class="card-body">
@if (HasBeenSend)
{
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Password reset email sent
</h1>
<div class="text-gray-400 fw-semibold fs-6">
You should receive the email shortly. If you see no email in your inbox, look inside your spam folder
</div>
</div>
}
else
{
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Reset your password
</h1>
<div class="text-gray-400 fw-semibold fs-6">
We will sent you an email to reset your account password
</div>
</div>
<SmartForm Model="Form" OnValidSubmit="OnValidSubmit">
<div class="fv-row mb-8">
<input @bind="Form.Email" type="text" placeholder="Email" class="form-control form-control-solid">
</div>
<div class="d-flex flex-stack">
<button type="submit" class="btn btn-primary me-2 flex-shrink-0">Continue</button>
</div>
</SmartForm>
}
</div>
</div>
@code
{
private bool HasBeenSend = false;
private ResetPasswordForm Form = new();
private async Task OnValidSubmit()
{
await UserService.Auth.SendResetPassword(Form.Email);
HasBeenSend = true;
await InvokeAsync(StateHasChanged);
}
}

View file

@ -1,79 +0,0 @@
@page "/register"
@* Virtual route to trick blazor *@
@using Moonlight.Core.Models.Forms
@using Moonlight.Core.Models.Forms.Auth
@using Moonlight.Core.Services
@using Moonlight.Core.Services.Users
@using MoonCore.Exceptions
@using MoonCoreUI.Services
@inject IdentityService IdentityService
@inject UserService UserService
@inject CookieService CookieService
@inject NavigationManager Navigation
<div class="w-100">
<div class="card-body">
<div class="text-start mb-8">
<h1 class="text-dark mb-3 fs-3x">
Sign Up
</h1>
<div class="text-gray-400 fw-semibold fs-6">
change me
</div>
</div>
<SmartForm Model="Form" OnValidSubmit="OnValidSubmit">
<div class="fv-row mb-8">
<input @bind="Form.Username" type="text" placeholder="Username" class="form-control form-control-solid">
</div>
<div class="fv-row mb-8">
<input @bind="Form.Email" type="text" placeholder="Email" class="form-control form-control-solid">
</div>
<div class="fv-row mb-7">
<input @bind="Form.Password" type="password" placeholder="Password" class="form-control form-control-solid">
</div>
<div class="fv-row mb-7">
<input @bind="Form.RepeatedPassword" type="password" placeholder="Repeat your password" class="form-control form-control-solid">
</div>
<div class="d-flex flex-stack flex-wrap gap-3 fs-base fw-semibold mb-10">
<div></div>
<a href="/login" class="link-primary">
Already have an account ?
</a>
</div>
<div class="d-flex flex-stack">
<button type="submit" class="btn btn-primary me-2 flex-shrink-0">Sign Up</button>
<div class="d-flex align-items-center">
<div class="text-gray-400 fw-semibold fs-6 me-3 me-md-6">Or</div>
@* OAuth2 Providers here *@
</div>
</div>
</SmartForm>
</div>
</div>
@code
{
private RegisterForm Form = new();
private async Task OnValidSubmit()
{
if (Form.Password != Form.RepeatedPassword)
throw new DisplayException("The passwords do not match");
var user = await UserService.Auth.Register(Form.Username, Form.Email, Form.Password);
var token = await IdentityService.GenerateToken(user);
await CookieService.SetValue("token", token);
await IdentityService.Authenticate(token);
if (Navigation.Uri.EndsWith("/register"))
Navigation.NavigateTo("/");
}
}

View file

@ -1,176 +0,0 @@
@inject IJSRuntime JsRuntime
@using Microsoft.AspNetCore.Components.Forms
@using Ganss.Xss
@using MoonCore.Helpers
@using Moonlight.Core.Services
@inherits InputBase<string>
@inject IdentityService IdentityService
<style>
:root {
/*
Fix from https://ckeditor.com/docs/ckeditor5/latest/installation/integrations/css.html
to make the editor work with bootstrap
*/
--ck-z-default: 100;
--ck-z-modal: calc( var(--ck-z-default) + 999 );
/* Overrides the border radius setting in the theme. */
--ck-border-radius: 4px;
/* Overrides the default font size in the theme. */
--ck-font-size-base: 14px;
/* Helper variables to avoid duplication in the colors. */
--ck-custom-background: #1e1e2d;
--ck-custom-foreground: hsl(255, 3%, 18%);
--ck-custom-border: hsl(300, 1%, 22%);
--ck-custom-white: hsl(0, 0%, 100%);
/* -- Overrides generic colors. ------------------------------------------------------------- */
--ck-color-base-foreground: var(--ck-custom-background);
--ck-color-focus-border: hsl(208, 90%, 62%);
--ck-color-text: hsl(0, 0%, 98%);
--ck-color-shadow-drop: hsla(0, 0%, 0%, 0.2);
--ck-color-shadow-inner: hsla(0, 0%, 0%, 0.1);
/* -- Overrides the default .ck-button class colors. ---------------------------------------- */
--ck-color-button-default-background: var(--ck-custom-background);
--ck-color-button-default-hover-background: hsl(270, 1%, 22%);
--ck-color-button-default-active-background: hsl(270, 2%, 20%);
--ck-color-button-default-active-shadow: hsl(270, 2%, 23%);
--ck-color-button-default-disabled-background: var(--ck-custom-background);
--ck-color-button-on-background: var(--ck-custom-foreground);
--ck-color-button-on-hover-background: hsl(255, 4%, 16%);
--ck-color-button-on-active-background: hsl(255, 4%, 14%);
--ck-color-button-on-active-shadow: hsl(240, 3%, 19%);
--ck-color-button-on-disabled-background: var(--ck-custom-foreground);
--ck-color-button-action-background: hsl(168, 76%, 42%);
--ck-color-button-action-hover-background: hsl(168, 76%, 38%);
--ck-color-button-action-active-background: hsl(168, 76%, 36%);
--ck-color-button-action-active-shadow: hsl(168, 75%, 34%);
--ck-color-button-action-disabled-background: hsl(168, 76%, 42%);
--ck-color-button-action-text: var(--ck-custom-white);
/* -- Overrides the default .ck-dropdown class colors. -------------------------------------- */
--ck-color-dropdown-panel-background: var(--ck-custom-background);
--ck-color-dropdown-panel-border: var(--ck-custom-foreground);
/* -- Overrides the default .ck-splitbutton class colors. ----------------------------------- */
--ck-color-split-button-hover-background: var(--ck-color-button-default-hover-background);
--ck-color-split-button-hover-border: var(--ck-custom-foreground);
/* -- Overrides the default .ck-input class colors. ----------------------------------------- */
--ck-color-input-background: var(--ck-custom-background);
--ck-color-input-border: hsl(257, 3%, 43%);
--ck-color-input-text: hsl(0, 0%, 98%);
--ck-color-input-disabled-background: hsl(255, 4%, 21%);
--ck-color-input-disabled-border: hsl(250, 3%, 38%);
--ck-color-input-disabled-text: hsl(0, 0%, 78%);
/* -- Overrides the default .ck-labeled-field-view class colors. ---------------------------- */
--ck-color-labeled-field-label-background: var(--ck-custom-background);
/* -- Overrides the default .ck-list class colors. ------------------------------------------ */
--ck-color-list-background: var(--ck-custom-background);
--ck-color-list-button-hover-background: var(--ck-custom-foreground);
--ck-color-list-button-on-background: hsl(208, 88%, 52%);
--ck-color-list-button-on-text: var(--ck-custom-white);
/* -- Overrides the default .ck-balloon-panel class colors. --------------------------------- */
--ck-color-panel-background: var(--ck-custom-background);
--ck-color-panel-border: var(--ck-custom-border);
/* -- Overrides the default .ck-toolbar class colors. --------------------------------------- */
--ck-color-toolbar-background: var(--ck-custom-background);
--ck-color-toolbar-border: var(--ck-custom-border);
/* -- Overrides the default .ck-tooltip class colors. --------------------------------------- */
--ck-color-tooltip-background: hsl(252, 7%, 14%);
--ck-color-tooltip-text: hsl(0, 0%, 93%);
/* -- Overrides the default colors used by the ckeditor5-image package. --------------------- */
--ck-color-image-caption-background: hsl(0, 0%, 97%);
--ck-color-image-caption-text: hsl(0, 0%, 20%);
/* -- Overrides the default colors used by the ckeditor5-widget package. -------------------- */
--ck-color-widget-blurred-border: hsl(0, 0%, 87%);
--ck-color-widget-hover-border: hsl(43, 100%, 68%);
--ck-color-widget-editable-focus-background: var(--ck-custom-white);
/* -- Overrides the default colors used by the ckeditor5-link package. ---------------------- */
--ck-color-link-default: hsl(190, 100%, 75%);
}
</style>
<div id="@Id" class="card card-body bg-black @(CssClasses)" @onfocusout="Callback" style="@(Styles)"></div>
@code
{
[Parameter]
public string InitialContent { get; set; }
[Parameter]
public string CssClasses { get; set; } = "";
[Parameter]
public string Styles { get; set; } = ""; // We added this parameter to allow custom heights to be set
private string Id;
private bool IsInitialized = false;
protected override void OnInitialized()
{
Id = "editor" + GetHashCode();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JsRuntime.InvokeVoidAsync("moonlight.textEditor.create", Id);
await JsRuntime.InvokeVoidAsync("moonlight.textEditor.set", Id, InitialContent);
CurrentValue = InitialContent;
IsInitialized = true;
}
}
private async Task Callback()
{
if(!IsInitialized)
return;
var html = await JsRuntime.InvokeAsync<string>("moonlight.textEditor.get", Id);
var sanitizer = new HtmlSanitizer();
var sanitized = sanitizer.Sanitize(html);
if(sanitized != html)
Logger.Warn($"XSS attempt by {IdentityService.CurrentUserNullable?.Username ?? "Guest"}: {html}", "security");
CurrentValue = sanitized;
}
protected override bool TryParseValueFromString(string? value, out string result, out string? validationErrorMessage)
{
result = value;
validationErrorMessage = "";
return true;
}
}

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