feat(backend): add support conversations
This commit is contained in:
		
							parent
							
								
									a4ca0902a3
								
							
						
					
					
						commit
						ed3159c05d
					
				
					 12 changed files with 620 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -26,6 +26,9 @@ public class DatabaseContext : DbContext
 | 
			
		|||
    public DbSet<UserFlag> UserFlags { get; set; }
 | 
			
		||||
    public DbSet<MemberFlag> MemberFlags { get; set; }
 | 
			
		||||
 | 
			
		||||
    public DbSet<SupportConversation> SupportConversations { get; set; }
 | 
			
		||||
    public DbSet<SupportMessage> SupportMessages { get; set; }
 | 
			
		||||
 | 
			
		||||
    public DatabaseContext(Config config, ILoggerFactory? loggerFactory)
 | 
			
		||||
    {
 | 
			
		||||
        var connString = new NpgsqlConnectionStringBuilder(config.Database.Url)
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +91,9 @@ public class DatabaseContext : DbContext
 | 
			
		|||
        modelBuilder.Entity<UserFlag>().Navigation(f => f.PrideFlag).AutoInclude();
 | 
			
		||||
        modelBuilder.Entity<MemberFlag>().Navigation(f => f.PrideFlag).AutoInclude();
 | 
			
		||||
 | 
			
		||||
        modelBuilder.Entity<SupportMessage>().Property(m => m.Attachments).HasColumnType("jsonb");
 | 
			
		||||
        modelBuilder.Entity<SupportMessage>().Property(m => m.History).HasColumnType("jsonb");
 | 
			
		||||
 | 
			
		||||
        modelBuilder
 | 
			
		||||
            .HasDbFunction(typeof(DatabaseContext).GetMethod(nameof(FindFreeUserSid))!)
 | 
			
		||||
            .HasName("find_free_user_sid");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Foxnouns.Backend.Database.Models;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Infrastructure;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Migrations;
 | 
			
		||||
 | 
			
		||||
#nullable disable
 | 
			
		||||
 | 
			
		||||
namespace Foxnouns.Backend.Database.Migrations
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    [DbContext(typeof(DatabaseContext))]
 | 
			
		||||
    [Migration("20241003150352_AddSupportConversations")]
 | 
			
		||||
    public partial class AddSupportConversations : Migration
 | 
			
		||||
    {
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        protected override void Up(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "support_conversations",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    id = table.Column<long>(type: "bigint", nullable: false),
 | 
			
		||||
                    user_id = table.Column<long>(type: "bigint", nullable: false),
 | 
			
		||||
                    title = table.Column<string>(type: "text", nullable: false),
 | 
			
		||||
                    assigned_to_id = table.Column<long>(type: "bigint", nullable: true),
 | 
			
		||||
                    status = table.Column<int>(type: "integer", nullable: false),
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("pk_support_conversations", x => x.id);
 | 
			
		||||
                    table.ForeignKey(
 | 
			
		||||
                        name: "fk_support_conversations_users_assigned_to_id",
 | 
			
		||||
                        column: x => x.assigned_to_id,
 | 
			
		||||
                        principalTable: "users",
 | 
			
		||||
                        principalColumn: "id"
 | 
			
		||||
                    );
 | 
			
		||||
                    table.ForeignKey(
 | 
			
		||||
                        name: "fk_support_conversations_users_user_id",
 | 
			
		||||
                        column: x => x.user_id,
 | 
			
		||||
                        principalTable: "users",
 | 
			
		||||
                        principalColumn: "id",
 | 
			
		||||
                        onDelete: ReferentialAction.Cascade
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "support_messages",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    id = table.Column<long>(type: "bigint", nullable: false),
 | 
			
		||||
                    conversation_id = table.Column<long>(type: "bigint", nullable: false),
 | 
			
		||||
                    user_id = table.Column<long>(type: "bigint", nullable: false),
 | 
			
		||||
                    is_anonymous = table.Column<bool>(type: "boolean", nullable: false),
 | 
			
		||||
                    content = table.Column<string>(type: "text", nullable: true),
 | 
			
		||||
                    attachments = table.Column<List<SupportMessage.Attachment>>(
 | 
			
		||||
                        type: "jsonb",
 | 
			
		||||
                        nullable: false
 | 
			
		||||
                    ),
 | 
			
		||||
                    history = table.Column<List<SupportMessage.HistoryEntry>>(
 | 
			
		||||
                        type: "jsonb",
 | 
			
		||||
                        nullable: false
 | 
			
		||||
                    ),
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("pk_support_messages", x => x.id);
 | 
			
		||||
                    table.ForeignKey(
 | 
			
		||||
                        name: "fk_support_messages_support_conversations_conversation_id",
 | 
			
		||||
                        column: x => x.conversation_id,
 | 
			
		||||
                        principalTable: "support_conversations",
 | 
			
		||||
                        principalColumn: "id",
 | 
			
		||||
                        onDelete: ReferentialAction.Cascade
 | 
			
		||||
                    );
 | 
			
		||||
                    table.ForeignKey(
 | 
			
		||||
                        name: "fk_support_messages_users_user_id",
 | 
			
		||||
                        column: x => x.user_id,
 | 
			
		||||
                        principalTable: "users",
 | 
			
		||||
                        principalColumn: "id",
 | 
			
		||||
                        onDelete: ReferentialAction.Cascade
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "ix_support_conversations_assigned_to_id",
 | 
			
		||||
                table: "support_conversations",
 | 
			
		||||
                column: "assigned_to_id"
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "ix_support_conversations_user_id",
 | 
			
		||||
                table: "support_conversations",
 | 
			
		||||
                column: "user_id"
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "ix_support_messages_conversation_id",
 | 
			
		||||
                table: "support_messages",
 | 
			
		||||
                column: "conversation_id"
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "ix_support_messages_user_id",
 | 
			
		||||
                table: "support_messages",
 | 
			
		||||
                column: "user_id"
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        protected override void Down(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            migrationBuilder.DropTable(name: "support_messages");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(name: "support_conversations");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -266,6 +266,85 @@ namespace Foxnouns.Backend.Database.Migrations
 | 
			
		|||
                    b.ToTable("pride_flags", (string)null);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.SupportConversation", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<long>("Id")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("id");
 | 
			
		||||
 | 
			
		||||
                    b.Property<long?>("AssignedToId")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("assigned_to_id");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Status")
 | 
			
		||||
                        .HasColumnType("integer")
 | 
			
		||||
                        .HasColumnName("status");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Title")
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasColumnType("text")
 | 
			
		||||
                        .HasColumnName("title");
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("UserId")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("user_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id")
 | 
			
		||||
                        .HasName("pk_support_conversations");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("AssignedToId")
 | 
			
		||||
                        .HasDatabaseName("ix_support_conversations_assigned_to_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .HasDatabaseName("ix_support_conversations_user_id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("support_conversations", (string)null);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.SupportMessage", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<long>("Id")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("id");
 | 
			
		||||
 | 
			
		||||
                    b.Property<List<SupportMessage.Attachment>>("Attachments")
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasColumnType("jsonb")
 | 
			
		||||
                        .HasColumnName("attachments");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Content")
 | 
			
		||||
                        .HasColumnType("text")
 | 
			
		||||
                        .HasColumnName("content");
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("ConversationId")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("conversation_id");
 | 
			
		||||
 | 
			
		||||
                    b.Property<List<SupportMessage.HistoryEntry>>("History")
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasColumnType("jsonb")
 | 
			
		||||
                        .HasColumnName("history");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("IsAnonymous")
 | 
			
		||||
                        .HasColumnType("boolean")
 | 
			
		||||
                        .HasColumnName("is_anonymous");
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("UserId")
 | 
			
		||||
                        .HasColumnType("bigint")
 | 
			
		||||
                        .HasColumnName("user_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id")
 | 
			
		||||
                        .HasName("pk_support_messages");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("ConversationId")
 | 
			
		||||
                        .HasDatabaseName("ix_support_messages_conversation_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .HasDatabaseName("ix_support_messages_user_id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("support_messages", (string)null);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.TemporaryKey", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<long>("Id")
 | 
			
		||||
| 
						 | 
				
			
			@ -542,6 +621,46 @@ namespace Foxnouns.Backend.Database.Migrations
 | 
			
		|||
                        .HasConstraintName("fk_pride_flags_users_user_id");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.SupportConversation", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("Foxnouns.Backend.Database.Models.User", "AssignedTo")
 | 
			
		||||
                        .WithMany()
 | 
			
		||||
                        .HasForeignKey("AssignedToId")
 | 
			
		||||
                        .HasConstraintName("fk_support_conversations_users_assigned_to_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasOne("Foxnouns.Backend.Database.Models.User", "User")
 | 
			
		||||
                        .WithMany()
 | 
			
		||||
                        .HasForeignKey("UserId")
 | 
			
		||||
                        .OnDelete(DeleteBehavior.Cascade)
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasConstraintName("fk_support_conversations_users_user_id");
 | 
			
		||||
 | 
			
		||||
                    b.Navigation("AssignedTo");
 | 
			
		||||
 | 
			
		||||
                    b.Navigation("User");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.SupportMessage", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("Foxnouns.Backend.Database.Models.SupportConversation", "Conversation")
 | 
			
		||||
                        .WithMany()
 | 
			
		||||
                        .HasForeignKey("ConversationId")
 | 
			
		||||
                        .OnDelete(DeleteBehavior.Cascade)
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasConstraintName("fk_support_messages_support_conversations_conversation_id");
 | 
			
		||||
 | 
			
		||||
                    b.HasOne("Foxnouns.Backend.Database.Models.User", "User")
 | 
			
		||||
                        .WithMany()
 | 
			
		||||
                        .HasForeignKey("UserId")
 | 
			
		||||
                        .OnDelete(DeleteBehavior.Cascade)
 | 
			
		||||
                        .IsRequired()
 | 
			
		||||
                        .HasConstraintName("fk_support_messages_users_user_id");
 | 
			
		||||
 | 
			
		||||
                    b.Navigation("Conversation");
 | 
			
		||||
 | 
			
		||||
                    b.Navigation("User");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("Foxnouns.Backend.Database.Models.Token", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("Foxnouns.Backend.Database.Models.Application", "Application")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								Foxnouns.Backend/Database/Models/SupportConversation.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Foxnouns.Backend/Database/Models/SupportConversation.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
namespace Foxnouns.Backend.Database.Models;
 | 
			
		||||
 | 
			
		||||
public class SupportConversation : BaseModel
 | 
			
		||||
{
 | 
			
		||||
    public Snowflake UserId { get; init; }
 | 
			
		||||
    public User User { get; init; } = null!;
 | 
			
		||||
    public required string Title { get; set; }
 | 
			
		||||
    public Snowflake? AssignedToId { get; set; }
 | 
			
		||||
    public User? AssignedTo { get; set; }
 | 
			
		||||
 | 
			
		||||
    public SupportConversationStatus Status { get; set; } = SupportConversationStatus.Open;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public enum SupportConversationStatus
 | 
			
		||||
{
 | 
			
		||||
    Open,
 | 
			
		||||
    Resolved,
 | 
			
		||||
    Closed,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								Foxnouns.Backend/Database/Models/SupportMessage.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Foxnouns.Backend/Database/Models/SupportMessage.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
using NodaTime;
 | 
			
		||||
 | 
			
		||||
namespace Foxnouns.Backend.Database.Models;
 | 
			
		||||
 | 
			
		||||
public class SupportMessage : BaseModel
 | 
			
		||||
{
 | 
			
		||||
    public Snowflake ConversationId { get; init; }
 | 
			
		||||
    public SupportConversation Conversation { get; init; } = null!;
 | 
			
		||||
    public Snowflake UserId { get; init; }
 | 
			
		||||
    public User User { get; init; } = null!;
 | 
			
		||||
    public bool IsAnonymous { get; init; }
 | 
			
		||||
 | 
			
		||||
    public string? Content { get; set; }
 | 
			
		||||
 | 
			
		||||
    public List<Attachment> Attachments { get; set; } = [];
 | 
			
		||||
    public List<HistoryEntry> History { get; set; } = [];
 | 
			
		||||
 | 
			
		||||
    public class Attachment
 | 
			
		||||
    {
 | 
			
		||||
        public required Snowflake Id { get; init; }
 | 
			
		||||
        public required string Hash { get; init; }
 | 
			
		||||
        public required string ContentType { get; init; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class HistoryEntry
 | 
			
		||||
    {
 | 
			
		||||
        public required Instant Timestamp { get; init; }
 | 
			
		||||
        public required string? Content { get; init; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue