Fixed some bugs. Added admin ui. Added word filter
This commit is contained in:
parent
c4e7e10f5e
commit
122a205f92
20 changed files with 804 additions and 31 deletions
|
@ -27,10 +27,11 @@ public class DataContext : DbContext
|
|||
public DbSet<Coupon> Coupons { get; set; }
|
||||
public DbSet<CouponUse> CouponUses { get; set; }
|
||||
|
||||
// Posts
|
||||
// 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; }
|
||||
|
||||
public DataContext(ConfigService configService)
|
||||
{
|
||||
|
|
7
Moonlight/App/Database/Entities/Community/WordFilter.cs
Normal file
7
Moonlight/App/Database/Entities/Community/WordFilter.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Moonlight.App.Database.Entities.Community;
|
||||
|
||||
public class WordFilter
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
554
Moonlight/App/Database/Migrations/20231028214520_AddedWordFilter.Designer.cs
generated
Normal file
554
Moonlight/App/Database/Migrations/20231028214520_AddedWordFilter.Designer.cs
generated
Normal file
|
@ -0,0 +1,554 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.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.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Comments")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Likes")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("Likes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,6 +105,21 @@ namespace Moonlight.App.Database.Migrations
|
|||
b.ToTable("PostLikes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.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.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
12
Moonlight/App/Models/Forms/Admin/Community/AddWordFilter.cs
Normal file
12
Moonlight/App/Models/Forms/Admin/Community/AddWordFilter.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Community;
|
||||
|
||||
public class AddWordFilter
|
||||
{
|
||||
[Required(ErrorMessage = "You need to specify a filter")]
|
||||
[Description(
|
||||
"This filters all posts and comments created using this regex. If any match is found it will block the action")]
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
12
Moonlight/App/Models/Forms/Admin/Community/EditWordFilter.cs
Normal file
12
Moonlight/App/Models/Forms/Admin/Community/EditWordFilter.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Community;
|
||||
|
||||
public class EditWordFilter
|
||||
{
|
||||
[Required(ErrorMessage = "You need to specify a filter")]
|
||||
[Description(
|
||||
"This filters all posts and comments created using this regex. If any match is found it will block the action")]
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
|
@ -15,17 +15,29 @@ public class PostService
|
|||
private readonly Repository<Post> PostRepository;
|
||||
private readonly Repository<PostLike> PostLikeRepository;
|
||||
private readonly Repository<PostComment> PostCommentRepository;
|
||||
private readonly Repository<WordFilter> WordFilterRepository;
|
||||
|
||||
public PostService(Repository<Post> postRepository, Repository<PostLike> postLikeRepository, Repository<PostComment> postCommentRepository)
|
||||
public PostService(
|
||||
Repository<Post> postRepository,
|
||||
Repository<PostLike> postLikeRepository,
|
||||
Repository<PostComment> postCommentRepository,
|
||||
Repository<WordFilter> wordFilterRepository)
|
||||
{
|
||||
PostRepository = postRepository;
|
||||
PostLikeRepository = postLikeRepository;
|
||||
PostCommentRepository = postCommentRepository;
|
||||
WordFilterRepository = wordFilterRepository;
|
||||
}
|
||||
|
||||
// Posts
|
||||
public async Task<Post> Create(User user, string title, string content, PostType type)
|
||||
{
|
||||
if(await CheckTextForBadWords(title))
|
||||
throw new DisplayException("Bad word detected. Please follow the community rules");
|
||||
|
||||
if(await CheckTextForBadWords(content))
|
||||
throw new DisplayException("Bad word detected. Please follow the community rules");
|
||||
|
||||
var post = new Post()
|
||||
{
|
||||
Author = user,
|
||||
|
@ -43,6 +55,12 @@ public class PostService
|
|||
|
||||
public async Task Update(Post post, string title, string content)
|
||||
{
|
||||
if(await CheckTextForBadWords(title))
|
||||
throw new DisplayException("Bad word detected. Please follow the community rules");
|
||||
|
||||
if(await CheckTextForBadWords(content))
|
||||
throw new DisplayException("Bad word detected. Please follow the community rules");
|
||||
|
||||
post.Title = title;
|
||||
post.Content = content;
|
||||
post.UpdatedAt = DateTime.UtcNow;
|
||||
|
@ -95,6 +113,9 @@ public class PostService
|
|||
if (!Regex.IsMatch(content, "^[ a-zA-Z0-9äöüßÄÖÜẞ,.;_\\n\\t-]+$"))
|
||||
throw new DisplayException("Illegal characters in comment content");
|
||||
|
||||
if(await CheckTextForBadWords(content))
|
||||
throw new DisplayException("Bad word detected. Please follow the community rules");
|
||||
|
||||
//TODO: Swear word filter
|
||||
|
||||
var comment = new PostComment()
|
||||
|
@ -157,4 +178,23 @@ public class PostService
|
|||
await Events.OnPostLiked.InvokeAsync(postWithLikes);
|
||||
}
|
||||
}
|
||||
|
||||
// Utils
|
||||
private Task<bool> CheckTextForBadWords(string input) // This method checks for bad words using the filters added by an admin
|
||||
{
|
||||
var filters = WordFilterRepository
|
||||
.Get()
|
||||
.Select(x => x.Filter)
|
||||
.ToArray();
|
||||
|
||||
//TODO: Add timer for regex matching to create warnings
|
||||
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
if (Regex.IsMatch(input, filter))
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
|
@ -57,7 +57,14 @@
|
|||
</li>
|
||||
<li class="nav-item">
|
||||
<a @onclick="ToggleLike" @onclick:preventDefault href="#" class="nav-link btn btn-sm btn-color-gray-600 btn-active-color-danger fw-bold px-4 me-1 @(HasLiked ? "active" : "")">
|
||||
<i class="bx bx-heart fs-2 me-1"></i>
|
||||
@if (HasLiked)
|
||||
{
|
||||
<i class="bx bxs-heart fs-2 me-1"></i>
|
||||
}
|
||||
else
|
||||
{
|
||||
<i class="bx bx-heart fs-2 me-1"></i>
|
||||
}
|
||||
@(LikesCount) Like(s)
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<SmartForm Model="CreateForm" OnValidSubmit="FinishCreate">
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<AutoForm Columns="6" Model="CreateForm"/>
|
||||
<AutoForm Columns="@(CreateForm.GetType().GetProperties().Length > 1 ? 6 : 12)" Model="CreateForm"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
@ -72,7 +72,7 @@
|
|||
<SmartForm Model="UpdateForm" OnValidSubmit="FinishUpdate">
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<AutoForm Columns="6" Model="UpdateForm"/>
|
||||
<AutoForm Columns="@(UpdateForm.GetType().GetProperties().Length > 1 ? 6 : 12)" Model="UpdateForm"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Title</label>
|
||||
<div class="form-text fs-5 mb-2 mt-0">
|
||||
This title is used for the preview of posts. It will not be shown in a regular post view
|
||||
</div>
|
||||
<input @bind="Form.Title" class="form-control form-control-solid-bg"/>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<div class="card mb-5 mb-xl-10">
|
||||
<div class="card-body pt-0 pb-0">
|
||||
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
||||
<li class="nav-item mt-2">
|
||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/community">
|
||||
<i class="bx bx-sm bx-group me-2"></i> Overview
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mt-2">
|
||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/community/filter">
|
||||
<i class="bx bx-sm bx-filter-alt me-2"></i> Filter
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter]
|
||||
public int Index { get; set; }
|
||||
}
|
|
@ -94,6 +94,17 @@
|
|||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="menu-item">
|
||||
<a class="menu-link " href="/admin/community">
|
||||
<span class="menu-icon">
|
||||
<i class="bx bx-sm bx-group"></i>
|
||||
</span>
|
||||
<span class="menu-title">
|
||||
Community
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
38
Moonlight/Shared/Views/Admin/Community/Filter.razor
Normal file
38
Moonlight/Shared/Views/Admin/Community/Filter.razor
Normal file
|
@ -0,0 +1,38 @@
|
|||
@page "/admin/community/filter"
|
||||
|
||||
@using Moonlight.App.Extensions.Attributes
|
||||
@using Moonlight.App.Models.Enums
|
||||
@using BlazorTable
|
||||
@using Moonlight.App.Database.Entities.Community
|
||||
@using Moonlight.App.Models.Forms.Admin.Community
|
||||
@using Moonlight.App.Repositories
|
||||
|
||||
@attribute [RequirePermission(Permission.AdminCommunity)]
|
||||
|
||||
<AdminCommunityNavigation Index="1" />
|
||||
|
||||
<div class="card card-body border-primary fs-5 mt-5">
|
||||
To protect from trollers and toxic people you can configure words using
|
||||
regex expressions to block automatically to ensure no one can write bad things in the community tab.
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<AutoCrud TItem="WordFilter"
|
||||
TCreateForm="AddWordFilter"
|
||||
TUpdateForm="EditWordFilter"
|
||||
Title="Manage word filter"
|
||||
Load="LoadData">
|
||||
<Column TableItem="WordFilter" Field="@(x => x.Id)" Title="Id" Sortable="false" Filterable="true" />
|
||||
<Column TableItem="WordFilter" Field="@(x => x.Filter)" Title="Filter" Sortable="false" Filterable="true" />
|
||||
</AutoCrud>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
private WordFilter[] LoadData(Repository<WordFilter> repository)
|
||||
{
|
||||
return repository
|
||||
.Get()
|
||||
.ToArray();
|
||||
}
|
||||
}
|
8
Moonlight/Shared/Views/Admin/Community/Index.razor
Normal file
8
Moonlight/Shared/Views/Admin/Community/Index.razor
Normal file
|
@ -0,0 +1,8 @@
|
|||
@page "/admin/community"
|
||||
|
||||
@using Moonlight.App.Extensions.Attributes
|
||||
@using Moonlight.App.Models.Enums
|
||||
|
||||
@attribute [RequirePermission(Permission.AdminCommunity)]
|
||||
|
||||
<AdminCommunityNavigation Index="0" />
|
|
@ -3,8 +3,12 @@
|
|||
@using Moonlight.App.Database.Entities.Store
|
||||
@using Moonlight.App.Repositories
|
||||
@using BlazorTable
|
||||
@using Moonlight.App.Extensions.Attributes
|
||||
@using Moonlight.App.Models.Enums
|
||||
@using Moonlight.App.Models.Forms.Admin.Store
|
||||
|
||||
@attribute [RequirePermission(Permission.AdminStore)]
|
||||
|
||||
@inject Repository<Coupon> CouponRepository
|
||||
|
||||
<AdminStoreNavigation Index="1"/>
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
@using Moonlight.App.Models.Forms.Admin.Store
|
||||
@using Moonlight.App.Repositories
|
||||
@using BlazorTable
|
||||
@using Moonlight.App.Extensions.Attributes
|
||||
@using Moonlight.App.Models.Enums
|
||||
|
||||
@attribute [RequirePermission(Permission.AdminStore)]
|
||||
|
||||
@inject Repository<GiftCode> GiftCodeRepository
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
@page "/admin/store"
|
||||
|
||||
@using Moonlight.App.Extensions.Attributes
|
||||
@using Moonlight.App.Models.Enums
|
||||
|
||||
@attribute [RequirePermission(Permission.AdminStore)]
|
||||
|
||||
<AdminStoreNavigation Index="0"/>
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-12 mb-5">
|
||||
<CommunityNavigation Index="1" />
|
||||
|
||||
<CommunityNavigation Index="1"/>
|
||||
|
||||
@if (IdentityService.Permissions[Permission.AdminCommunity])
|
||||
{
|
||||
<div class="card card-body mt-5">
|
||||
|
@ -24,28 +24,26 @@
|
|||
}
|
||||
</div>
|
||||
<div class="col-md-10 col-12">
|
||||
<div class="card border-primary">
|
||||
<div class="card border-primary mb-5">
|
||||
<div class="card-body fs-5">
|
||||
Planned events and current happenings can be found here.
|
||||
If you want to know what will happen in the future or is going on now have a look at the posts below
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
@foreach (var post in Posts)
|
||||
{
|
||||
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
|
||||
<div class="mb-10"></div>
|
||||
}
|
||||
</LazyLoader>
|
||||
</div>
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
@foreach (var post in Posts)
|
||||
{
|
||||
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
|
||||
<div class="mb-10"></div>
|
||||
}
|
||||
</LazyLoader>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (IdentityService.Permissions[Permission.AdminCommunity])
|
||||
{
|
||||
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Event" />
|
||||
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Event"/>
|
||||
}
|
||||
|
||||
@code
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-12 mb-5">
|
||||
<CommunityNavigation Index="2" />
|
||||
|
||||
<CommunityNavigation Index="2"/>
|
||||
|
||||
<div class="card card-body mt-5">
|
||||
<button @onclick="() => CreateModal.Show()" class="btn btn-success">Create new post</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-10 col-12">
|
||||
<div class="card border-primary">
|
||||
<div class="card border-primary mb-5">
|
||||
<div class="card-body fs-5">
|
||||
You have a interesting project or a fun game server you want to share with the community?
|
||||
You can share it here. Please keep in mind to follow basic rules and dont offend anyone.
|
||||
|
@ -26,19 +26,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
@foreach (var post in Posts)
|
||||
{
|
||||
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
|
||||
<div class="mb-10"></div>
|
||||
}
|
||||
</LazyLoader>
|
||||
</div>
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
@foreach (var post in Posts)
|
||||
{
|
||||
<PostView Post="post" OnUpdate="() => LazyLoader.Reload()"/>
|
||||
<div class="mb-10"></div>
|
||||
}
|
||||
</LazyLoader>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Event" />
|
||||
<CreatePostModal @ref="CreateModal" OnUpdate="() => LazyLoader.Reload()" PostType="PostType.Project"/>
|
||||
|
||||
@code
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue