diff --git a/SQLQuery1.sql b/SQLQuery1.sql new file mode 100644 index 0000000..aec18fb --- /dev/null +++ b/SQLQuery1.sql @@ -0,0 +1 @@ +delete from Comments ; \ No newline at end of file diff --git a/SciQuery.Domain/Entities/Answer.cs b/SciQuery.Domain/Entities/Answer.cs index 089e478..5cfcc0a 100644 --- a/SciQuery.Domain/Entities/Answer.cs +++ b/SciQuery.Domain/Entities/Answer.cs @@ -4,16 +4,16 @@ namespace SciQuery.Domain.Entities; public class Answer { public int Id { get; set; } + public string? Body { get; set; } + public int Votes { get; set; } = 0; + public List? ImagePaths { get; set; } + public DateTime CreatedDate { get; set; } = DateTime.Now; + public DateTime? UpdatedDate { get; set; } = DateTime.Now; public int QuestionId { get; set; } public Question Question { get; set; } public string UserId { get; set; } public User User { get; set; } - public string? Body { get; set; } - public List? ImagePath { get; set; } - public DateTime CreatedDate { get; set; } = DateTime.Now; - public DateTime? UpdatedDate { get; set; } = DateTime.Now; - public virtual ICollection Votes { get; set; } public virtual ICollection Comments{ get; set; } diff --git a/SciQuery.Domain/Entities/Comment.cs b/SciQuery.Domain/Entities/Comment.cs index d374b3d..5ffc8da 100644 --- a/SciQuery.Domain/Entities/Comment.cs +++ b/SciQuery.Domain/Entities/Comment.cs @@ -7,10 +7,8 @@ public class Comment public int Id { get; set; } public string UserId { get; set; } public User User { get; set; } - public int? QuestionId { get; set; } - public Question Question { get; set; } - public int? AnswerId { get; set; } - public Answer Answer { get; set; } + public int PostId { get; set; } + public PostType Post{ get; set; } public string Body { get; set; } public DateTime CreatedDate { get; set; } = DateTime.Now; } diff --git a/SciQuery.Domain/Entities/PostType.cs b/SciQuery.Domain/Entities/PostType.cs new file mode 100644 index 0000000..01c09e5 --- /dev/null +++ b/SciQuery.Domain/Entities/PostType.cs @@ -0,0 +1,7 @@ +namespace SciQuery.Domain.Entities; + +public enum PostType +{ + Answer, + Question +} diff --git a/SciQuery.Domain/Entities/Question.cs b/SciQuery.Domain/Entities/Question.cs index 5132a44..09e9c5a 100644 --- a/SciQuery.Domain/Entities/Question.cs +++ b/SciQuery.Domain/Entities/Question.cs @@ -5,19 +5,20 @@ namespace SciQuery.Domain.Entities; public class Question { public int Id { get; set; } - public string UserId { get; set; } - public User User { get; set; } public string? Title { get; set; } public string? Body { get; set; } - public List? ImagePath { get; set; } + public int Votes { get; set; } = 0; + public List? ImagePaths { get; set; } public DateTime CreatedDate { get; set; } = DateTime.Now; - public DateTime? UpdatedDate { get; set; } + public DateTime? UpdatedDate { get; set; } = DateTime.Now; + public string UserId { get; set; } + public User User { get; set; } public virtual ICollection Answers { get; set; } public virtual ICollection Comments { get; set; } public virtual ICollection QuestionTags { get; set; } - public virtual ICollection Votes { get; set; } public Question() { + ImagePaths = new List(); Answers = new List(); Comments = new List(); QuestionTags = new List(); diff --git a/SciQuery.Domain/Entities/Vote.cs b/SciQuery.Domain/Entities/Vote.cs deleted file mode 100644 index 23712c6..0000000 --- a/SciQuery.Domain/Entities/Vote.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SciQuery.Domain.UserModels; -using SciQuery.Domain.Votes; - -namespace SciQuery.Domain.Entities; - -public class Vote -{ - public int Id { get; set; } - public string UserId { get; set; } - public User User { get; set; } - public int? QuestionId { get; set; } - public Question Question { get; set; } - public int? AnswerId { get; set; } - public Answer Answer { get; set; } - public VoteEnum VoteType { get; set; } - -} diff --git a/SciQuery.Domain/SciQuery.Domain.csproj b/SciQuery.Domain/SciQuery.Domain.csproj index 66c7d1d..0f02192 100644 --- a/SciQuery.Domain/SciQuery.Domain.csproj +++ b/SciQuery.Domain/SciQuery.Domain.csproj @@ -8,6 +8,7 @@ + diff --git a/SciQuery.Domain/UserModels/User.cs b/SciQuery.Domain/UserModels/User.cs index 6e033aa..dafc234 100644 --- a/SciQuery.Domain/UserModels/User.cs +++ b/SciQuery.Domain/UserModels/User.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Identity; +using SciQuery.Domain.Entities; using System.Globalization; namespace SciQuery.Domain.UserModels; @@ -9,4 +10,13 @@ public class User : IdentityUser public int Reputation { get; set; } public DateTime CreatedDate { get; set; } public DateTime LastLogindate { get; set; } + public virtual ICollection Answers{ get; set; } + public virtual ICollection Questions{ get; set; } + public virtual ICollection Comments{ get; set; } + public User() + { + Answers = new List(); + Questions = new List(); + Comments = new List(); + } } diff --git a/SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.Designer.cs b/SciQuery.Infrastructure/Migrations/20240808143552_1.Designer.cs similarity index 97% rename from SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.Designer.cs rename to SciQuery.Infrastructure/Migrations/20240808143552_1.Designer.cs index d19dda8..d5c5c85 100644 --- a/SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.Designer.cs +++ b/SciQuery.Infrastructure/Migrations/20240808143552_1.Designer.cs @@ -12,8 +12,8 @@ namespace SciQuery.Infrastructure.Migrations { [DbContext(typeof(SciQueryDbContext))] - [Migration("20240801145616_Intial_Create")] - partial class Intial_Create + [Migration("20240808143552_1")] + partial class _1 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -212,6 +212,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("CreatedDate") .HasColumnType("datetime2"); + b.Property("Post") + .HasColumnType("int"); + + b.Property("PostId") + .HasColumnType("int"); + b.Property("QuestionId") .HasColumnType("int"); @@ -227,7 +233,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("Comment", (string)null); + b.ToTable("Comments"); }); modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => @@ -344,6 +350,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("AnswerId") .HasColumnType("int"); + b.Property("Post") + .HasColumnType("int"); + + b.Property("PostId") + .HasColumnType("int"); + b.Property("QuestionId") .HasColumnType("int"); @@ -514,11 +526,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => { - b.HasOne("SciQuery.Domain.Entities.Answer", "Answer") + b.HasOne("SciQuery.Domain.Entities.Answer", null) .WithMany("Comments") .HasForeignKey("AnswerId"); - b.HasOne("SciQuery.Domain.Entities.Question", "Question") + b.HasOne("SciQuery.Domain.Entities.Question", null) .WithMany("Comments") .HasForeignKey("QuestionId"); @@ -528,10 +540,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Answer"); - - b.Navigation("Question"); - b.Navigation("User"); }); @@ -578,11 +586,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("SciQuery.Domain.Entities.Vote", b => { - b.HasOne("SciQuery.Domain.Entities.Answer", "Answer") + b.HasOne("SciQuery.Domain.Entities.Answer", null) .WithMany("Votes") .HasForeignKey("AnswerId"); - b.HasOne("SciQuery.Domain.Entities.Question", "Question") + b.HasOne("SciQuery.Domain.Entities.Question", null) .WithMany("Votes") .HasForeignKey("QuestionId"); @@ -592,10 +600,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Answer"); - - b.Navigation("Question"); - b.Navigation("User"); }); diff --git a/SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.cs b/SciQuery.Infrastructure/Migrations/20240808143552_1.cs similarity index 95% rename from SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.cs rename to SciQuery.Infrastructure/Migrations/20240808143552_1.cs index cc61f70..c3dfdf4 100644 --- a/SciQuery.Infrastructure/Migrations/20240801145616_Intial_Create.cs +++ b/SciQuery.Infrastructure/Migrations/20240808143552_1.cs @@ -6,7 +6,7 @@ namespace SciQuery.Infrastructure.Migrations { /// - public partial class Intial_Create : Migration + public partial class _1 : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -276,33 +276,35 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Comment", + name: "Comments", columns: table => new { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), UserId = table.Column(type: "nvarchar(450)", nullable: false), - QuestionId = table.Column(type: "int", nullable: true), - AnswerId = table.Column(type: "int", nullable: true), + PostId = table.Column(type: "int", nullable: false), + Post = table.Column(type: "int", nullable: false), Body = table.Column(type: "nvarchar(max)", nullable: false), - CreatedDate = table.Column(type: "datetime2", nullable: false) + CreatedDate = table.Column(type: "datetime2", nullable: false), + AnswerId = table.Column(type: "int", nullable: true), + QuestionId = table.Column(type: "int", nullable: true) }, constraints: table => { - table.PrimaryKey("PK_Comment", x => x.Id); + table.PrimaryKey("PK_Comments", x => x.Id); table.ForeignKey( - name: "FK_Comment_Answer_AnswerId", + name: "FK_Comments_Answer_AnswerId", column: x => x.AnswerId, principalTable: "Answer", principalColumn: "Id"); table.ForeignKey( - name: "FK_Comment_AspNetUsers_UserId", + name: "FK_Comments_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_Comment_Question_QuestionId", + name: "FK_Comments_Question_QuestionId", column: x => x.QuestionId, principalTable: "Question", principalColumn: "Id"); @@ -315,9 +317,11 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), UserId = table.Column(type: "nvarchar(450)", nullable: false), - QuestionId = table.Column(type: "int", nullable: true), + PostId = table.Column(type: "int", nullable: false), + Post = table.Column(type: "int", nullable: false), + VoteType = table.Column(type: "int", nullable: false), AnswerId = table.Column(type: "int", nullable: true), - VoteType = table.Column(type: "int", nullable: false) + QuestionId = table.Column(type: "int", nullable: true) }, constraints: table => { @@ -390,18 +394,18 @@ protected override void Up(MigrationBuilder migrationBuilder) filter: "[NormalizedUserName] IS NOT NULL"); migrationBuilder.CreateIndex( - name: "IX_Comment_AnswerId", - table: "Comment", + name: "IX_Comments_AnswerId", + table: "Comments", column: "AnswerId"); migrationBuilder.CreateIndex( - name: "IX_Comment_QuestionId", - table: "Comment", + name: "IX_Comments_QuestionId", + table: "Comments", column: "QuestionId"); migrationBuilder.CreateIndex( - name: "IX_Comment_UserId", - table: "Comment", + name: "IX_Comments_UserId", + table: "Comments", column: "UserId"); migrationBuilder.CreateIndex( @@ -459,7 +463,7 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "AspNetUserTokens"); migrationBuilder.DropTable( - name: "Comment"); + name: "Comments"); migrationBuilder.DropTable( name: "QuestionTag"); diff --git a/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.Designer.cs b/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.Designer.cs new file mode 100644 index 0000000..d9a8255 --- /dev/null +++ b/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.Designer.cs @@ -0,0 +1,576 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SciQuery.Infrastructure.Persistance.DbContext; + +#nullable disable + +namespace SciQuery.Infrastructure.Migrations +{ + [DbContext(typeof(SciQueryDbContext))] + [Migration("20240808161144_DeleteVote")] + partial class DeleteVote + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("ImagePath") + .HasColumnType("nvarchar(max)"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("UpdatedDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("UserId"); + + b.ToTable("Answer", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AnswerId") + .HasColumnType("int"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Post") + .HasColumnType("int"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("AnswerId"); + + b.HasIndex("QuestionId"); + + b.HasIndex("UserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("ImagePath") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Question", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.QuestionTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("TagId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("TagId"); + + b.ToTable("QuestionTag", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.ReputationChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChangeAmount") + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ReputationChange", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Tag", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.UserModels.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LastLogindate") + .HasColumnType("datetime2"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfileImagePath") + .HasColumnType("nvarchar(max)"); + + b.Property("Reputation") + .HasColumnType("int"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.HasOne("SciQuery.Domain.Entities.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => + { + b.HasOne("SciQuery.Domain.Entities.Answer", null) + .WithMany("Comments") + .HasForeignKey("AnswerId"); + + b.HasOne("SciQuery.Domain.Entities.Question", null) + .WithMany("Comments") + .HasForeignKey("QuestionId"); + + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.QuestionTag", b => + { + b.HasOne("SciQuery.Domain.Entities.Question", "Question") + .WithMany("QuestionTags") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.Entities.Tag", "Tag") + .WithMany("QuestionTags") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.ReputationChange", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.Navigation("Answers"); + + b.Navigation("Comments"); + + b.Navigation("QuestionTags"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Tag", b => + { + b.Navigation("QuestionTags"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.cs b/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.cs new file mode 100644 index 0000000..e112707 --- /dev/null +++ b/SciQuery.Infrastructure/Migrations/20240808161144_DeleteVote.cs @@ -0,0 +1,92 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SciQuery.Infrastructure.Migrations +{ + /// + public partial class DeleteVote : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Vote"); + + migrationBuilder.AddColumn( + name: "Votes", + table: "Question", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Votes", + table: "Answer", + type: "int", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Votes", + table: "Question"); + + migrationBuilder.DropColumn( + name: "Votes", + table: "Answer"); + + migrationBuilder.CreateTable( + name: "Vote", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + AnswerId = table.Column(type: "int", nullable: true), + Post = table.Column(type: "int", nullable: false), + PostId = table.Column(type: "int", nullable: false), + QuestionId = table.Column(type: "int", nullable: true), + VoteType = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Vote", x => x.Id); + table.ForeignKey( + name: "FK_Vote_Answer_AnswerId", + column: x => x.AnswerId, + principalTable: "Answer", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Vote_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Vote_Question_QuestionId", + column: x => x.QuestionId, + principalTable: "Question", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_Vote_AnswerId", + table: "Vote", + column: "AnswerId"); + + migrationBuilder.CreateIndex( + name: "IX_Vote_QuestionId", + table: "Vote", + column: "QuestionId"); + + migrationBuilder.CreateIndex( + name: "IX_Vote_UserId", + table: "Vote", + column: "UserId"); + } + } +} diff --git a/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.Designer.cs b/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.Designer.cs new file mode 100644 index 0000000..4c8668d --- /dev/null +++ b/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.Designer.cs @@ -0,0 +1,585 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SciQuery.Infrastructure.Persistance.DbContext; + +#nullable disable + +namespace SciQuery.Infrastructure.Migrations +{ + [DbContext(typeof(SciQueryDbContext))] + [Migration("20240816122027_changeNameImagePathtoImagePaths")] + partial class changeNameImagePathtoImagePaths + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("ImagePaths") + .HasColumnType("nvarchar(max)"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("UpdatedDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("UserId"); + + b.ToTable("Answer", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AnswerId") + .HasColumnType("int"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Post") + .HasColumnType("int"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("AnswerId"); + + b.HasIndex("QuestionId"); + + b.HasIndex("UserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("ImagePaths") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatedDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Votes") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Question", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.QuestionTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("QuestionId") + .HasColumnType("int"); + + b.Property("TagId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("TagId"); + + b.ToTable("QuestionTag", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.ReputationChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChangeAmount") + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ReputationChange", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Tag", (string)null); + }); + + modelBuilder.Entity("SciQuery.Domain.UserModels.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LastLogindate") + .HasColumnType("datetime2"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfileImagePath") + .HasColumnType("nvarchar(max)"); + + b.Property("Reputation") + .HasColumnType("int"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.HasOne("SciQuery.Domain.Entities.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany("Answers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => + { + b.HasOne("SciQuery.Domain.Entities.Answer", null) + .WithMany("Comments") + .HasForeignKey("AnswerId"); + + b.HasOne("SciQuery.Domain.Entities.Question", null) + .WithMany("Comments") + .HasForeignKey("QuestionId"); + + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany("Comments") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany("Questions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.QuestionTag", b => + { + b.HasOne("SciQuery.Domain.Entities.Question", "Question") + .WithMany("QuestionTags") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SciQuery.Domain.Entities.Tag", "Tag") + .WithMany("QuestionTags") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.ReputationChange", b => + { + b.HasOne("SciQuery.Domain.UserModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => + { + b.Navigation("Answers"); + + b.Navigation("Comments"); + + b.Navigation("QuestionTags"); + }); + + modelBuilder.Entity("SciQuery.Domain.Entities.Tag", b => + { + b.Navigation("QuestionTags"); + }); + + modelBuilder.Entity("SciQuery.Domain.UserModels.User", b => + { + b.Navigation("Answers"); + + b.Navigation("Comments"); + + b.Navigation("Questions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.cs b/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.cs new file mode 100644 index 0000000..c0caab6 --- /dev/null +++ b/SciQuery.Infrastructure/Migrations/20240816122027_changeNameImagePathtoImagePaths.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SciQuery.Infrastructure.Migrations +{ + /// + public partial class changeNameImagePathtoImagePaths : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ImagePath", + table: "Question", + newName: "ImagePaths"); + + migrationBuilder.RenameColumn( + name: "ImagePath", + table: "Answer", + newName: "ImagePaths"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ImagePaths", + table: "Question", + newName: "ImagePath"); + + migrationBuilder.RenameColumn( + name: "ImagePaths", + table: "Answer", + newName: "ImagePath"); + } + } +} diff --git a/SciQuery.Infrastructure/Migrations/SciQueryDbContextModelSnapshot.cs b/SciQuery.Infrastructure/Migrations/SciQueryDbContextModelSnapshot.cs index 0598ec0..d052a96 100644 --- a/SciQuery.Infrastructure/Migrations/SciQueryDbContextModelSnapshot.cs +++ b/SciQuery.Infrastructure/Migrations/SciQueryDbContextModelSnapshot.cs @@ -169,7 +169,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedDate") .HasColumnType("datetime2"); - b.Property("ImagePath") + b.Property("ImagePaths") .HasColumnType("nvarchar(max)"); b.Property("QuestionId") @@ -182,6 +182,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("Votes") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("QuestionId"); @@ -209,6 +212,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedDate") .HasColumnType("datetime2"); + b.Property("Post") + .HasColumnType("int"); + + b.Property("PostId") + .HasColumnType("int"); + b.Property("QuestionId") .HasColumnType("int"); @@ -224,7 +233,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("Comment", (string)null); + b.ToTable("Comments"); }); modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => @@ -241,7 +250,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedDate") .HasColumnType("datetime2"); - b.Property("ImagePath") + b.Property("ImagePaths") .HasColumnType("nvarchar(max)"); b.Property("Title") @@ -254,6 +263,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(450)"); + b.Property("Votes") + .HasColumnType("int"); + b.HasKey("Id"); b.HasIndex("UserId"); @@ -330,38 +342,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Tag", (string)null); }); - modelBuilder.Entity("SciQuery.Domain.Entities.Vote", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AnswerId") - .HasColumnType("int"); - - b.Property("QuestionId") - .HasColumnType("int"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("VoteType") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AnswerId"); - - b.HasIndex("QuestionId"); - - b.HasIndex("UserId"); - - b.ToTable("Vote", (string)null); - }); - modelBuilder.Entity("SciQuery.Domain.UserModels.User", b => { b.Property("Id") @@ -499,7 +479,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); b.HasOne("SciQuery.Domain.UserModels.User", "User") - .WithMany() + .WithMany("Answers") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -511,31 +491,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("SciQuery.Domain.Entities.Comment", b => { - b.HasOne("SciQuery.Domain.Entities.Answer", "Answer") + b.HasOne("SciQuery.Domain.Entities.Answer", null) .WithMany("Comments") .HasForeignKey("AnswerId"); - b.HasOne("SciQuery.Domain.Entities.Question", "Question") + b.HasOne("SciQuery.Domain.Entities.Question", null) .WithMany("Comments") .HasForeignKey("QuestionId"); b.HasOne("SciQuery.Domain.UserModels.User", "User") - .WithMany() + .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Answer"); - - b.Navigation("Question"); - b.Navigation("User"); }); modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => { b.HasOne("SciQuery.Domain.UserModels.User", "User") - .WithMany() + .WithMany("Questions") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -573,34 +549,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("SciQuery.Domain.Entities.Vote", b => - { - b.HasOne("SciQuery.Domain.Entities.Answer", "Answer") - .WithMany("Votes") - .HasForeignKey("AnswerId"); - - b.HasOne("SciQuery.Domain.Entities.Question", "Question") - .WithMany("Votes") - .HasForeignKey("QuestionId"); - - b.HasOne("SciQuery.Domain.UserModels.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Answer"); - - b.Navigation("Question"); - - b.Navigation("User"); - }); - modelBuilder.Entity("SciQuery.Domain.Entities.Answer", b => { b.Navigation("Comments"); - - b.Navigation("Votes"); }); modelBuilder.Entity("SciQuery.Domain.Entities.Question", b => @@ -610,14 +561,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Comments"); b.Navigation("QuestionTags"); - - b.Navigation("Votes"); }); modelBuilder.Entity("SciQuery.Domain.Entities.Tag", b => { b.Navigation("QuestionTags"); }); + + modelBuilder.Entity("SciQuery.Domain.UserModels.User", b => + { + b.Navigation("Answers"); + + b.Navigation("Comments"); + + b.Navigation("Questions"); + }); #pragma warning restore 612, 618 } } diff --git a/SciQuery.Infrastructure/Persistance/DbContext/SciQueryDbContext.cs b/SciQuery.Infrastructure/Persistance/DbContext/SciQueryDbContext.cs index 9ceb88b..74895b9 100644 --- a/SciQuery.Infrastructure/Persistance/DbContext/SciQueryDbContext.cs +++ b/SciQuery.Infrastructure/Persistance/DbContext/SciQueryDbContext.cs @@ -14,71 +14,16 @@ public class SciQueryDbContext(DbContextOptions options, public virtual DbSet Questions { get; set; } public virtual DbSet Answers { get; set; } public virtual DbSet Tags { get; set; } - public virtual DbSet Votes { get; set; } public virtual DbSet ReputationChanges { get; set; } public virtual DbSet QuestionTags { get; set; } protected override void OnModelCreating(ModelBuilder builder) { - builder.Entity(entity => - { - entity.HasKey(q => q.Id); - - entity.HasMany(q => q.QuestionTags) - .WithOne(qt => qt.Question) - .HasForeignKey(qt => qt.QuestionId); - - entity.HasMany(q => q.Answers) - .WithOne(a => a.Question) - .HasForeignKey(a => a.QuestionId); - - entity.HasMany(q => q.Comments) - .WithOne(c => c.Question) - .HasForeignKey(c => c.QuestionId); - - entity.HasMany(q => q.Votes) - .WithOne(v => v.Question) - .HasForeignKey(v => v.QuestionId); - }); - - builder.Entity(entity => - { - entity.HasKey(qt => qt.Id); - - entity.HasOne(qt => qt.Question) - .WithMany(q => q.QuestionTags) - .HasForeignKey(qt => qt.QuestionId); - - entity.HasOne(qt => qt.Tag) - .WithMany(t => t.QuestionTags) - .HasForeignKey(qt => qt.TagId); - }); - - builder.Entity(entity => - { - entity.HasKey(t => t.Id); - }); - - builder.Entity().ToTable(nameof(Comment)); - - builder.Entity() - .HasOne(c => c.Question) - .WithMany(q => q.Comments) - .HasForeignKey(c => c.QuestionId) - .OnDelete(DeleteBehavior.Cascade); - - builder.Entity() - .HasOne(c => c.Answer) - .WithMany(a => a.Comments) - .HasForeignKey(c => c.AnswerId) - .OnDelete(DeleteBehavior.Cascade); - + builder.Entity().ToTable(nameof(Answer)); builder.Entity().ToTable(nameof(Tag)); - builder.Entity().ToTable(nameof(Vote)); - builder.Entity().ToTable(nameof(Question)); builder.Entity().ToTable(nameof(QuestionTag)); @@ -90,7 +35,7 @@ protected override void OnModelCreating(ModelBuilder builder) } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnectionMuhammad")); + optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnectionFirdavs")); base.OnConfiguring(optionsBuilder); } } diff --git a/SciQuery.Infrastructure/SciQuery.Infrastructure.csproj b/SciQuery.Infrastructure/SciQuery.Infrastructure.csproj index f2ef7b5..5822332 100644 --- a/SciQuery.Infrastructure/SciQuery.Infrastructure.csproj +++ b/SciQuery.Infrastructure/SciQuery.Infrastructure.csproj @@ -7,6 +7,7 @@ + all diff --git a/SciQuery.Service/DTOs/Answer/AnswerDto.cs b/SciQuery.Service/DTOs/Answer/AnswerDto.cs index 9a7f21c..ade91d3 100644 --- a/SciQuery.Service/DTOs/Answer/AnswerDto.cs +++ b/SciQuery.Service/DTOs/Answer/AnswerDto.cs @@ -1,11 +1,5 @@ using SciQuery.Service.DTOs.Comment; using SciQuery.Service.DTOs.User; -using SciQuery.Service.DTOs.Vote; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SciQuery.Service.DTOs.Answer { @@ -19,7 +13,13 @@ public class AnswerDto public string UserId { get; set; } public UserDto User { get; set; } - public ICollection Votes { get; set; } + public int Votes { get; set; } = 0; public ICollection Comments { get; set; } + public ICollection Images { get; set; } + public AnswerDto() + { + Images = new List(); + Comments = new List(); + } } } diff --git a/SciQuery.Service/DTOs/Answer/AnswerForUpdateDto.cs b/SciQuery.Service/DTOs/Answer/AnswerForUpdateDto.cs index 5bcb24c..0f8c22d 100644 --- a/SciQuery.Service/DTOs/Answer/AnswerForUpdateDto.cs +++ b/SciQuery.Service/DTOs/Answer/AnswerForUpdateDto.cs @@ -2,6 +2,6 @@ public class AnswerForUpdateDto { - public int Id { get; set; } public string Body { get; set; } + public string UserId { get; set; } } diff --git a/SciQuery.Service/DTOs/Comment/CommentDto.cs b/SciQuery.Service/DTOs/Comment/CommentDto.cs index 70a21bc..7b0d7e4 100644 --- a/SciQuery.Service/DTOs/Comment/CommentDto.cs +++ b/SciQuery.Service/DTOs/Comment/CommentDto.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.User; +using SciQuery.Domain.Entities; +using SciQuery.Service.DTOs.User; namespace SciQuery.Service.DTOs.Comment; @@ -6,8 +7,8 @@ public class CommentDto { public int Id { get; set; } public string Body { get; set; } - public int QuestionId { get; set; } - public int AnswerId { get; set; } + public int PostId { get; set; } + public PostType Post { get; set; } public string UserId { get; set; } public UserDto User { get; set; } } diff --git a/SciQuery.Service/DTOs/Comment/CommentForCreateDto.cs b/SciQuery.Service/DTOs/Comment/CommentForCreateDto.cs index 4f9363b..94fb153 100644 --- a/SciQuery.Service/DTOs/Comment/CommentForCreateDto.cs +++ b/SciQuery.Service/DTOs/Comment/CommentForCreateDto.cs @@ -1,4 +1,5 @@ -using System; +using SciQuery.Domain.Entities; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,8 +10,8 @@ namespace SciQuery.Service.DTOs.Comment public class CommentForCreateDto { public string Body { get; set; } - public int? QuestionId { get; set; } - public int? AnswerId { get; set; } + public int? PostId { get; set; } + public PostType Post { get; set; } public string UserId { get; set; } } diff --git a/SciQuery.Service/DTOs/Comment/CommentForUpdateDto.cs b/SciQuery.Service/DTOs/Comment/CommentForUpdateDto.cs index 0cbe0f2..4ee9fbb 100644 --- a/SciQuery.Service/DTOs/Comment/CommentForUpdateDto.cs +++ b/SciQuery.Service/DTOs/Comment/CommentForUpdateDto.cs @@ -8,8 +8,8 @@ namespace SciQuery.Service.DTOs.Comment { public class CommentForUpdateDto { - public int Id { get; set; } public string Body { get; set; } + public string UserId { get; set; } } } diff --git a/SciQuery.Service/DTOs/Question/ForEasyQestionDto.cs b/SciQuery.Service/DTOs/Question/ForEasyQestionDto.cs index 6ad4f25..64068b4 100644 --- a/SciQuery.Service/DTOs/Question/ForEasyQestionDto.cs +++ b/SciQuery.Service/DTOs/Question/ForEasyQestionDto.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.User; +using SciQuery.Service.DTOs.Tag; +using SciQuery.Service.DTOs.User; using System; using System.Collections.Generic; using System.Linq; @@ -9,7 +10,7 @@ namespace SciQuery.Service.DTOs.Question; public class ForEasyQestionDto { - public int Id { get; set; } + public int Id { get; set; } public string Title { get; set; } public string Body { get; set; } public DateTime CreatedDate { get; set; } @@ -17,8 +18,9 @@ public class ForEasyQestionDto public string UserId { get; set; } public UserDto User { get; set; } public int AnswersCount { get; set; } + public int CommentsCount { get; set; } public int Votes { get; set; } - public ICollection Tags { get; set; } + public ICollection Tags { get; set; } } diff --git a/SciQuery.Service/DTOs/Question/QuestionDto.cs b/SciQuery.Service/DTOs/Question/QuestionDto.cs index d4f6384..fc46f0d 100644 --- a/SciQuery.Service/DTOs/Question/QuestionDto.cs +++ b/SciQuery.Service/DTOs/Question/QuestionDto.cs @@ -1,9 +1,9 @@ -using SciQuery.Domain.Entities; +using Microsoft.AspNetCore.Http; +using SciQuery.Domain.Entities; using SciQuery.Service.DTOs.Answer; using SciQuery.Service.DTOs.Comment; using SciQuery.Service.DTOs.Tag; using SciQuery.Service.DTOs.User; -using SciQuery.Service.DTOs.Vote; namespace SciQuery.Service.DTOs.Question; @@ -12,12 +12,20 @@ public class QuestionDto public int Id { get; set; } public string Title { get; set; } public string Body { get; set; } + public int Votes { get; set; } = 0; + public List? Images { get; set; } public DateTime CreatedDate { get; set; } public DateTime UpdatedDate { get; set; } public string UserId { get; set; } public UserDto User { get; set; } - public ICollection Votes { get; set; } public ICollection Answers { get; set; } public ICollection Comments { get; set; } public ICollection Tags { get; set; } + public QuestionDto() + { + Images = []; + Answers = []; + Comments = []; + Tags = []; + } } diff --git a/SciQuery.Service/DTOs/Question/QuestionForCreateDto.cs b/SciQuery.Service/DTOs/Question/QuestionForCreateDto.cs index 50371d8..c16f16f 100644 --- a/SciQuery.Service/DTOs/Question/QuestionForCreateDto.cs +++ b/SciQuery.Service/DTOs/Question/QuestionForCreateDto.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.Tag; +using Microsoft.AspNetCore.Http; +using SciQuery.Service.DTOs.Tag; using System; using System.Collections.Generic; using System.Linq; @@ -12,6 +13,7 @@ public class QuestionForCreateDto public string Title { get; set; } public string Body { get; set; } public string? UserId { get; set; } + public ICollection? ImagePaths { get; set; } public ICollection Tags { get; set; } } diff --git a/SciQuery.Service/DTOs/Question/QuestionForUpdateDto.cs b/SciQuery.Service/DTOs/Question/QuestionForUpdateDto.cs index fe5be85..c9d323c 100644 --- a/SciQuery.Service/DTOs/Question/QuestionForUpdateDto.cs +++ b/SciQuery.Service/DTOs/Question/QuestionForUpdateDto.cs @@ -1,13 +1,11 @@ using SciQuery.Domain.Entities; using SciQuery.Service.DTOs.Answer; using SciQuery.Service.DTOs.Comment; -using SciQuery.Service.DTOs.Vote; namespace SciQuery.Service.DTOs.Question; public class QuestionForUpdateDto { - public int Id { get; set; } public string Title { get; set; } public string Body { get; set; } } diff --git a/SciQuery.Service/DTOs/User/ImageFile.cs b/SciQuery.Service/DTOs/User/ImageFile.cs new file mode 100644 index 0000000..026a8df --- /dev/null +++ b/SciQuery.Service/DTOs/User/ImageFile.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SciQuery.Service.DTOs.User +{ + public class ImageFile + { + public byte[] Bytes { get; set; } + public string ContentType { get; set; } + public string FileName { get; set; } + public ImageFile() + { + + } + public ImageFile(byte[] bytes, string contentType, string fileName) + { + Bytes = bytes; + ContentType = contentType; + FileName = fileName; + } + } +} diff --git a/SciQuery.Service/DTOs/User/UserDto.cs b/SciQuery.Service/DTOs/User/UserDto.cs index f082bca..1a515e1 100644 --- a/SciQuery.Service/DTOs/User/UserDto.cs +++ b/SciQuery.Service/DTOs/User/UserDto.cs @@ -6,6 +6,7 @@ public class UserDto public string UserName { get; set; } public string Email { get; set; } public int Reputation { get; set; } + public ImageFile Image { get; set; } public DateTime CreatedDate { get; set; } public DateTime LastLogindate { get; set; } = DateTime.Now; } diff --git a/SciQuery.Service/DTOs/User/UserForUpdatesDto.cs b/SciQuery.Service/DTOs/User/UserForUpdatesDto.cs index 2508f26..fd9a334 100644 --- a/SciQuery.Service/DTOs/User/UserForUpdatesDto.cs +++ b/SciQuery.Service/DTOs/User/UserForUpdatesDto.cs @@ -2,7 +2,7 @@ public class UserForUpdatesDto { - public int Id { get; set; } + public string Id { get; set; } public string UserName { get; set; } public string Email { get; set; } public int Reputation { get; set; } diff --git a/SciQuery.Service/DTOs/Vote/VoteDto.cs b/SciQuery.Service/DTOs/Vote/VoteDto.cs deleted file mode 100644 index 7a57e0b..0000000 --- a/SciQuery.Service/DTOs/Vote/VoteDto.cs +++ /dev/null @@ -1,14 +0,0 @@ -using SciQuery.Domain.Votes; -using SciQuery.Service.DTOs.User; - -namespace SciQuery.Service.DTOs.Vote; - -public class VoteDto -{ - public int Id { get; set; } - public VoteEnum VoteEnum { get; set; } - public int QuestionId { get; set; } - public int AnswerId { get; set; } - public string UserId { get; set; } - public UserDto User { get; set; } -} diff --git a/SciQuery.Service/DTOs/Vote/VoteForCreateDto.cs b/SciQuery.Service/DTOs/Vote/VoteForCreateDto.cs deleted file mode 100644 index 357f549..0000000 --- a/SciQuery.Service/DTOs/Vote/VoteForCreateDto.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SciQuery.Domain.Votes; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SciQuery.Service.DTOs.Vote -{ - public class VoteForCreateDto - { - public VoteEnum VoteEnum { get; set; } - public int QuestionId { get; set; } - public int AnswerId { get; set; } - public string UserId { get; set; } - } -} diff --git a/SciQuery.Service/Hubs/NotificationHub.cs b/SciQuery.Service/Hubs/NotificationHub.cs new file mode 100644 index 0000000..9eea597 --- /dev/null +++ b/SciQuery.Service/Hubs/NotificationHub.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; +[Authorize] +public class NotificationHub : Hub +{ + // Bildirishnoma yuborish metodini yaratish + public async Task SendNotification(string message) + { + // Foydalanuvchiga bildirishnoma yuborish + await Clients.All.SendAsync("ReceiveNotification", message); + } + [Authorize] + public override async Task OnConnectedAsync() + { + var userId = Context.UserIdentifier; + await Groups.AddToGroupAsync(Context.ConnectionId, userId); + await base.OnConnectedAsync(); + } + +} +public class NotificationService(IHubContexthubcontext) +{ + private readonly IHubContext _hubcontext = hubcontext; + + public async Task NotifyUser(string userId, string message) + { + await _hubcontext.Clients.Group(userId).SendAsync("ReceiveNotification", message); + + } +} + diff --git a/SciQuery.Service/Interfaces/IAnswerService.cs b/SciQuery.Service/Interfaces/IAnswerService.cs index 7f2e1ad..8549188 100644 --- a/SciQuery.Service/Interfaces/IAnswerService.cs +++ b/SciQuery.Service/Interfaces/IAnswerService.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.Answer; +using Microsoft.AspNetCore.Http; +using SciQuery.Service.DTOs.Answer; using SciQuery.Service.DTOs.Question; using SciQuery.Service.Pagination.PaginatedList; @@ -9,6 +10,7 @@ public interface IAnswerService Task> GetAllAnswersByQuestionIdAsync(int questionId); Task GetByIdAsync(int id); Task CreateAsync(AnswerForCreateDto answer); + Task CreateImages(IFormFile file); Task UpdateAsync(int id, AnswerForUpdateDto answer); Task DeleteAsync(int id); } diff --git a/SciQuery.Service/Interfaces/ICommentService.cs b/SciQuery.Service/Interfaces/ICommentService.cs index 3a6d4dd..dd95fd2 100644 --- a/SciQuery.Service/Interfaces/ICommentService.cs +++ b/SciQuery.Service/Interfaces/ICommentService.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.Comment; +using SciQuery.Domain.Entities; +using SciQuery.Service.DTOs.Comment; namespace SciQuery.Service.Interfaces; @@ -11,4 +12,5 @@ public interface ICommentService Task CreateCommentAsync(CommentForCreateDto commentCreateDto); Task UpdateCommentAsync(int id, CommentForUpdateDto commentUpdateDto); Task DeleteCommentAsync(int id); + Task DeleteCommentByPostIdAsync(PostType postType,int postId); } diff --git a/SciQuery.Service/Interfaces/IFileManagingService.cs b/SciQuery.Service/Interfaces/IFileManagingService.cs new file mode 100644 index 0000000..524ec95 --- /dev/null +++ b/SciQuery.Service/Interfaces/IFileManagingService.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Http; +using SciQuery.Service.DTOs.User; + +namespace SciQuery.Service.Interfaces; + +public interface IFileManagingService +{ + Task UploadFile(IFormFile file,params string[] imagePath); + + Task DownloadFileAsync(string fileName,string filePath); +} diff --git a/SciQuery.Service/Interfaces/IQuestionService.cs b/SciQuery.Service/Interfaces/IQuestionService.cs index 53944be..c561003 100644 --- a/SciQuery.Service/Interfaces/IQuestionService.cs +++ b/SciQuery.Service/Interfaces/IQuestionService.cs @@ -1,4 +1,5 @@ -using SciQuery.Domain.Entities; +using Microsoft.AspNetCore.Http; +using SciQuery.Domain.Entities; using SciQuery.Service.DTOs.Question; using SciQuery.Service.DTOs.Tag; using SciQuery.Service.Pagination.PaginatedList; @@ -11,7 +12,10 @@ public interface IQuestionService Task> GetQuestionsByTags(QuestionQueryParameters queryParams); Task> GetAllAsync(QuestionQueryParameters queryParams); Task GetByIdAsync(int id); - Task CreateAsync(QuestionForCreateDto questionDto); + + Task CreateAsync(QuestionForCreateDto question); + Task CreateImages(IFormFile file); + Task UpdateAsync(int id,QuestionForUpdateDto question); Task DeleteAsync(int id); } diff --git a/SciQuery.Service/Interfaces/IUserService.cs b/SciQuery.Service/Interfaces/IUserService.cs index 49cacff..3c76f85 100644 --- a/SciQuery.Service/Interfaces/IUserService.cs +++ b/SciQuery.Service/Interfaces/IUserService.cs @@ -1,4 +1,5 @@ -using SciQuery.Service.DTOs.User; +using Microsoft.AspNetCore.Http; +using SciQuery.Service.DTOs.User; using SciQuery.Service.Pagination.PaginatedList; namespace SciQuery.Service.Interfaces; @@ -7,6 +8,10 @@ public interface IUserService Task> GetAllAsync(); Task GetByIdAsync(string id); Task CreateAsync(UserForCreateDto userCreateDto); + + Task CreateImage(IFormFile file); + Task UpdateAsync(string id, UserForUpdatesDto userUpdateDto); Task DeleteAsync(string id); + } diff --git a/SciQuery.Service/Interfaces/IVoteService.cs b/SciQuery.Service/Interfaces/IVoteService.cs deleted file mode 100644 index 2c40429..0000000 --- a/SciQuery.Service/Interfaces/IVoteService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using SciQuery.Service.DTOs.Vote; -using SciQuery.Service.Pagination.PaginatedList; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SciQuery.Service.Interfaces -{ - public interface IVoteService - { - Task> GetVoteByUserIdAsync(string userId); - Task> GetAllVotesByQuestionIdAsync(int questionId); - Task> GetAllVotesByAnswerIdAsync(int answerId); - Task CreateVoteAsync(VoteForCreateDto voteCreateDto); - Task DeleteVoteAsync(int id); - } -} diff --git a/SciQuery.Service/Mappings/CommentMappings.cs b/SciQuery.Service/Mappings/CommentMappings.cs index 9ab31a0..051c66f 100644 --- a/SciQuery.Service/Mappings/CommentMappings.cs +++ b/SciQuery.Service/Mappings/CommentMappings.cs @@ -11,6 +11,7 @@ public CommentMappings() CreateMap(); CreateMap(); CreateMap(); + } } } diff --git a/SciQuery.Service/Mappings/ForEasyQuestionMappings.cs b/SciQuery.Service/Mappings/ForEasyQuestionMappings.cs index cad76e5..704aa48 100644 --- a/SciQuery.Service/Mappings/ForEasyQuestionMappings.cs +++ b/SciQuery.Service/Mappings/ForEasyQuestionMappings.cs @@ -10,8 +10,7 @@ public ForEasyQuestionMappings() { CreateMap() .ForMember(dest => dest.AnswersCount, opt => opt.MapFrom(src => src.Answers.Count)) - .ForMember(dest => dest.Votes, opt => opt.MapFrom(src => src.Votes.Count)) - .ForMember(dest => dest.Tags, opt => opt.MapFrom(src => src.QuestionTags.Select(qt => qt.Tag.Name))); + .ForMember(dest => dest.Tags, opt => opt.MapFrom(src => src.QuestionTags.Select(qt => qt.Tag))); } } } diff --git a/SciQuery.Service/Mappings/QuestionMappins.cs b/SciQuery.Service/Mappings/QuestionMappins.cs index fe0e544..789e4e8 100644 --- a/SciQuery.Service/Mappings/QuestionMappins.cs +++ b/SciQuery.Service/Mappings/QuestionMappins.cs @@ -13,7 +13,9 @@ public QuestionMappings() .ForMember(dest => dest.Tags, opt => opt .MapFrom(src => src.QuestionTags.Select(qt => qt.Tag.Name) .ToList())); - + + CreateMap(); + CreateMap(); CreateMap(); } diff --git a/SciQuery.Service/Mappings/VoteMappings.cs b/SciQuery.Service/Mappings/VoteMappings.cs deleted file mode 100644 index 0751052..0000000 --- a/SciQuery.Service/Mappings/VoteMappings.cs +++ /dev/null @@ -1,14 +0,0 @@ -using AutoMapper; -using SciQuery.Domain.Entities; -using SciQuery.Service.DTOs.Vote; - -namespace SciQuery.Service.Mappings; - -public class VoteMappings : Profile -{ - public VoteMappings() - { - CreateMap(); - CreateMap(); - } -} diff --git a/SciQuery.Service/SciQuery.Service.csproj b/SciQuery.Service/SciQuery.Service.csproj index c741a7c..90ff682 100644 --- a/SciQuery.Service/SciQuery.Service.csproj +++ b/SciQuery.Service/SciQuery.Service.csproj @@ -8,6 +8,9 @@ + + + diff --git a/SciQuery.Service/Services/AnswerService.cs b/SciQuery.Service/Services/AnswerService.cs index c81ac87..4bed8f3 100644 --- a/SciQuery.Service/Services/AnswerService.cs +++ b/SciQuery.Service/Services/AnswerService.cs @@ -1,65 +1,130 @@ using AutoMapper; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using SciQuery.Domain.Entities; using SciQuery.Domain.Exceptions; using SciQuery.Infrastructure.Persistance.DbContext; using SciQuery.Service.DTOs.Answer; +using SciQuery.Service.DTOs.Comment; using SciQuery.Service.Interfaces; -using SciQuery.Service.Mappings.Extensions; +using AutoMapper.QueryableExtensions; using SciQuery.Service.Pagination.PaginatedList; +using SciQuery.Service.Mappings.Extensions; +using Microsoft.AspNetCore.SignalR; +using SciQuery.Domain.UserModels; +using SciQuery.Service.DTOs.User; namespace SciQuery.Service.Services; -public class AnswerService(SciQueryDbContext context, IMapper mapper) : IAnswerService +public class AnswerService(SciQueryDbContext context, + IMapper mapper, + IFileManagingService fileManaging, + ICommentService commentService, + IHubContext hubContext) : IAnswerService { - private readonly SciQueryDbContext _context = context; - private readonly IMapper _mapper = mapper; + private readonly SciQueryDbContext _context = context + ??throw new ArgumentNullException(nameof(context)); + private readonly IMapper _mapper = mapper + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly IFileManagingService _fileManaging = fileManaging + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly ICommentService _commentService = commentService; + private readonly IHubContext _hubContext = hubContext; public async Task GetByIdAsync(int id) { var answer = await _context.Answers + .AsQueryable() .Include(a => a.User) .Include(a => a.Question) .Include(a => a.Comments) - .Include(a => a.Votes) .AsNoTracking() .AsSplitQuery() .FirstOrDefaultAsync(a => a.Id == id) ?? throw new EntityNotFoundException($"Answer with id : {id} is not found!"); - return _mapper.Map(answer); + answer.Comments = await _context.Comments + .Where(c => c.Post == PostType.Question && c.PostId == id) + .AsNoTracking() + .ToListAsync(); + + var dto = _mapper.Map(answer); + + var images = new List(); + + foreach (var imagePath in answer.ImagePaths) + { + var image = await fileManaging.DownloadFileAsync(imagePath, "AnswerImages"); + images.Add(image); + } + dto.Images = images; + + return dto; } public async Task> GetAllAnswersByQuestionIdAsync(int questionId) { + // Step 1: Fetch all answers for the given question var answers = await _context.Answers - .Include(a => a.User) - .Include(a => a.Question) - .Include(a => a.Votes) + .Include(a => a.User) // Include the user who posted the answer .Where(a => a.QuestionId == questionId) .OrderBy(a => a.Id) .AsNoTracking() - .AsSplitQuery() - .AsSingleQuery() .ToPaginatedList(_mapper.ConfigurationProvider, 1, 15); + // Step 2: Fetch comments for all answers + var answerIds = answers.Data + .Select(a => a.Id) + .ToList(); + + var comments = await _context.Comments + .Include(c => c.User) // Include the user who posted the comment + .Where(c => answerIds.Contains(c.PostId) && c.Post == PostType.Answer) + .ProjectTo(_mapper.ConfigurationProvider) + .ToListAsync(); + + // Step 3: Associate comments with their respective answers + foreach (var answer in answers.Data) + { + answer.Comments = comments + .Where(c => c.PostId == answer.Id) + .ToList(); + } + return answers; } - public async Task CreateAsync(AnswerForCreateDto answerCreateDto) { var answer = _mapper.Map(answerCreateDto); answer.CreatedDate = DateTime.Now; + answer.UpdatedDate = DateTime.Now; _context.Answers.Add(answer); await _context.SaveChangesAsync(); + // Savolni yaratgan foydalanuvchiga bildirishnoma yuborish + var question = await _context.Questions + .Include(q => q.User) + .FirstOrDefaultAsync(q => q.Id == answer.QuestionId); + + if (question != null) + { + await _hubContext.Clients.All + .SendAsync("ReceiveNotification", "Sizning savolingizga yangi javob qo'shildi!"); + } + return _mapper.Map(answer); } + + public async Task CreateImages(IFormFile file) + { + return await _fileManaging.UploadFile(file,"Source","Images","AnswerImages"); + } + public async Task UpdateAsync(int id, AnswerForUpdateDto answerUpdateDto) { - var answer = await _context.Answers.FindAsync(id) + var answer = await _context.Answers.FirstOrDefaultAsync(c => c.Id == id) ?? throw new EntityNotFoundException($"Answer with id : {id} is not found!"); answer.UpdatedDate = DateTime.Now; @@ -70,13 +135,14 @@ public async Task UpdateAsync(int id, AnswerForUpdateDto answerUpdateDto) public async Task DeleteAsync(int id) { var answer = await _context.Answers - .Include(a => a.Comments) - .AsNoTracking() - .AsSplitQuery() .FirstOrDefaultAsync(a => a.Id == id) ?? throw new EntityNotFoundException($"Answer with id : {id} is not found!"); - - _context.Answers.Remove(answer); + + await _commentService.DeleteCommentByPostIdAsync(PostType.Answer, id); + + _context.Answers.Remove(answer); + await _context.SaveChangesAsync(); } + } diff --git a/SciQuery.Service/Services/CommentService.cs b/SciQuery.Service/Services/CommentService.cs index 76450b4..5c41ca7 100644 --- a/SciQuery.Service/Services/CommentService.cs +++ b/SciQuery.Service/Services/CommentService.cs @@ -31,7 +31,7 @@ public async Task GetCommentByIdAsync(int id) public async Task> GetAllCommentsByQuestionIdAsync(int questionId) { var comments = await _context.Comments - .Where(c => c.QuestionId == questionId) + .Where(c => c.Post == PostType.Question && c.PostId == questionId) .ToListAsync(); return _mapper.Map>(comments); } @@ -43,7 +43,7 @@ public Task GetCommentByUserIdAsync(int id) public async Task> GetAllCommentsByAnswerIdAsync(int answerId) { var comments = await _context.Comments - .Where(c => c.AnswerId == answerId) + .Where(c => c.Post == PostType.Answer && c.PostId == answerId) .ToListAsync(); return _mapper.Map>(comments); } @@ -60,12 +60,10 @@ public async Task CreateCommentAsync(CommentForCreateDto commentCrea public async Task UpdateCommentAsync(int id, CommentForUpdateDto commentUpdateDto) { - var comment = await _context.Comments.FindAsync(id); - if (comment == null) - { - return null; - } - + var comment = await _context.Comments + .FirstOrDefaultAsync(c => c.Id == id) + ?? throw new EntityNotFoundException("Comment not Found"); + _mapper.Map(commentUpdateDto, comment); await _context.SaveChangesAsync(); @@ -84,4 +82,14 @@ public async Task DeleteCommentAsync(int id) await _context.SaveChangesAsync(); return true; } + public async Task DeleteCommentByPostIdAsync(PostType postType,int postId) + { + var comments = await _context.Comments + .Where(c => c.Post == postType && c.PostId == postId) + .ToListAsync(); + + _context.Comments.RemoveRange(comments); + _context.SaveChanges(); + + } } diff --git a/SciQuery.Service/Services/FileManagingService.cs b/SciQuery.Service/Services/FileManagingService.cs new file mode 100644 index 0000000..43f4950 --- /dev/null +++ b/SciQuery.Service/Services/FileManagingService.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.StaticFiles; +using SciQuery.Service.DTOs.User; +using SciQuery.Service.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SciQuery.Service.Services; + +public class FileMangingService(FileExtensionContentTypeProvider fileExtension) : IFileManagingService +{ + private readonly FileExtensionContentTypeProvider _fileExtension = fileExtension; + + public async Task UploadFile(IFormFile file,params string[] imagePath) + { + if (file == null) + { + throw new ArgumentNullException("Files cannot be null or empty."); + } + + if (file.Length == 0 || file.Length > 1024 * 1024 * 40) + { + throw new ArgumentException("Each file must be an image with a size up to 40 MB."); + } + + var fileName = Guid.NewGuid() + file.FileName; + + var path = Directory.GetCurrentDirectory(); + + foreach(var directory in imagePath) + { + path = Path.Combine(path, directory); + } + + path = Path.Combine(path, fileName); + + using (var stream = new FileStream(path, FileMode.Create)) + { + await file.CopyToAsync(stream); + } + + return fileName; + } + + public async Task DownloadFileAsync(string fileName,string filePath) + { + var path = Path.Combine(Directory.GetCurrentDirectory(), "Source"); + + if (File.Exists(Path.Combine(path, "Images",filePath, fileName))) + { + path = Path.Combine(path, "images",filePath, fileName); + } + else + { + throw new FileNotFoundException("File not found."); + } + + if (!_fileExtension.TryGetContentType(path, out string contentType)) + { + contentType = "application/octet-stream"; + } + + var bytes = await System.IO.File.ReadAllBytesAsync(path); + + var image = new ImageFile(bytes, contentType, Path.GetFileName(path)); + return image; + } +} diff --git a/SciQuery.Service/Services/QuestionService.cs b/SciQuery.Service/Services/QuestionService.cs index 23dedef..9c8d71a 100644 --- a/SciQuery.Service/Services/QuestionService.cs +++ b/SciQuery.Service/Services/QuestionService.cs @@ -1,11 +1,11 @@ using AutoMapper; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; using SciQuery.Domain.Entities; using SciQuery.Domain.Exceptions; using SciQuery.Infrastructure.Persistance.DbContext; +using SciQuery.Service.DTOs.Comment; using SciQuery.Service.DTOs.Question; -using SciQuery.Service.DTOs.Tag; using SciQuery.Service.Interfaces; using SciQuery.Service.Mappings.Extensions; using SciQuery.Service.Pagination.PaginatedList; @@ -13,11 +13,19 @@ namespace SciQuery.Service.Services; -public class QuestionService(SciQueryDbContext dbContext,IMapper mapper,IAnswerService answerService,ICommentService commentService) : IQuestionService +public class QuestionService(SciQueryDbContext dbContext, + IMapper mapper, + IFileManagingService fileManaging, + ICommentService commentService) + : IQuestionService { - private readonly SciQueryDbContext _context = dbContext; - private readonly IMapper _mapper = mapper; - private readonly IAnswerService _answerService = answerService; + private readonly SciQueryDbContext _context = dbContext + ?? throw new ArgumentNullException(nameof(dbContext)); + private readonly IMapper _mapper = mapper + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly IFileManagingService _fileManaging = fileManaging + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly ICommentService _commentService = commentService; @@ -51,17 +59,17 @@ public async Task> GetQuestionsByTags(QuestionQ public async Task> GetAllAsync(QuestionQueryParameters queryParams) { var query = _context.Questions - .Include(q => q.User) - .Include(q => q.Answers) - .Include(q => q.Votes) - .Include(q => q.QuestionTags) - .ThenInclude(qt => qt.Tag) - .AsNoTracking() - .AsQueryable(); + .AsQueryable() + .Include(q => q.User) + .Include(q => q.Answers) + .Include(q => q.QuestionTags) + .ThenInclude(qt => qt.Tag) + .AsNoTracking(); + if (!string.IsNullOrEmpty(queryParams.Search)) { - query = query.Where(q => q.Title.Contains(queryParams.Search) + query = query.Where(q => q.Title.Contains(queryParams.Search) || q.Body.Contains(queryParams.Search)); } @@ -89,30 +97,70 @@ public async Task> GetAllAsync(QuestionQueryPar query = query.OrderBy(x => x.UpdatedDate); } - var result = await query.ToPaginatedList(_mapper.ConfigurationProvider, 1, 15); + var result = await query + .Include(a => a.Answers) + .ToPaginatedList(_mapper.ConfigurationProvider, 1, 15); + + var questionIds = await query + .Select(q => q.Id) + .ToListAsync(); + + var comments = await _context.Comments + .Where(c => questionIds.Contains(c.PostId) && c.Post == PostType.Question) + .GroupBy(c => c.PostId) + .Select(g => new + { + PostId = g.Key, + Count = g.Count() + }) + .ToListAsync(); + + foreach (var question in result.Data) + { + var comment = comments.FirstOrDefault(c => c.PostId == question.Id); + question.CommentsCount = comment != null ? comment.Count : 0; + } + return result; } public async Task GetByIdAsync(int id) { var question = await _context.Questions + .Where(q => q.Id == id) .Include(q => q.User) + .Include(q => q.Answers) .Include(q => q.QuestionTags) .ThenInclude(qt => qt.Tag) - .Include(q => q.Comments) - .Include(q => q.Votes) .AsNoTracking() - .AsSplitQuery() - .FirstOrDefaultAsync(q => q.Id == id); + .FirstOrDefaultAsync(q => q.Id == id) + ?? throw new EntityNotFoundException($"Question does not found {id}"); + question.Comments = await _context.Comments + .Where(c => c.Post == PostType.Question && c.PostId == id) + .AsNoTracking() + .ToListAsync(); + var dto = _mapper.Map(question); + if(question.ImagePaths == null || question.ImagePaths.Count < 1) + { + return dto; + } + + foreach (var imagePath in question.ImagePaths) + { + var image = await fileManaging.DownloadFileAsync(imagePath,"QuestionImages"); + dto.Images!.Add(image); + } + return dto ?? throw new EntityNotFoundException($"Question with id : {id} is not found!"); } public async Task CreateAsync(QuestionForCreateDto questionCreateDto) { - // Question ob'ektini yaratish va xaritalash + + // Question ob'ektini yaratish va maplash var question = _mapper.Map(questionCreateDto); question.CreatedDate = DateTime.Now; question.UpdatedDate = DateTime.Now; @@ -159,6 +207,11 @@ public async Task CreateAsync(QuestionForCreateDto questionCreateDt return _mapper.Map(question); } + public async Task CreateImages(IFormFile file) + { + return await _fileManaging.UploadFile(file, "Source", "Images", "QuestionImages"); + } + public async Task UpdateAsync(int id, QuestionForUpdateDto questionUpdateDto) { var question = await _context.Questions.FindAsync(id) @@ -173,33 +226,14 @@ public async Task UpdateAsync(int id, QuestionForUpdateDto questionUpdateDto) public async Task DeleteAsync(int id) { - var question = await _context.Questions.Include(c => c.Votes).Include(c => c.Comments).FirstOrDefaultAsync(x => x.Id == id); + var question = await _context.Questions.FirstOrDefaultAsync(q => q.Id == id); + if (question == null) { return false; } - var answers = _context.Answers.Where(a => a.QuestionId == id).Include(c => c.Comments) - .Include(c => c.Votes).ToList(); - - foreach (var i in answers) - { - _context.Comments.RemoveRange(i.Comments); - } - - foreach (var i in answers) - { - _context.Votes.RemoveRange(i.Votes); - } - await _context.SaveChangesAsync(); - - _context.Answers.RemoveRange(answers); - await _context.SaveChangesAsync(); - - - _context.Comments.RemoveRange(question.Comments); - _context.Votes.RemoveRange(question.Votes); - await _context.SaveChangesAsync(); + await _commentService.DeleteCommentByPostIdAsync(PostType.Question, question.Id); _context.Questions.Remove(question); await _context.SaveChangesAsync(); diff --git a/SciQuery.Service/Services/UserService.cs b/SciQuery.Service/Services/UserService.cs index 44b746a..cf70545 100644 --- a/SciQuery.Service/Services/UserService.cs +++ b/SciQuery.Service/Services/UserService.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using SciQuery.Domain.Entities; @@ -10,18 +11,19 @@ using SciQuery.Service.Mappings.Extensions; using SciQuery.Service.Pagination.PaginatedList; -public class UserService : IUserService -{ - private readonly SciQueryDbContext _context; - private readonly UserManager _userManager; - private readonly IMapper _mapper; +namespace SciQuery.Service.Services; - public UserService(SciQueryDbContext context ,UserManager userManager, IMapper mapper) - { - _context = context; - _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); - _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); - } +public class UserService(UserManager user,IMapper mapper, SciQueryDbContext context, IFileManagingService fileManaging, IAnswerService answerService) : IUserService +{ + private readonly IAnswerService _answerService = answerService; + private readonly UserManager _userManager = user + ?? throw new ArgumentNullException(nameof(user)); + private readonly IMapper _mapper = mapper + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly IFileManagingService _fileManaging = fileManaging + ?? throw new ArgumentNullException(nameof(mapper)); + private readonly SciQueryDbContext _context = context + ?? throw new ArgumentNullException(nameof(context)); public async Task> GetAllAsync() { @@ -34,12 +36,14 @@ public async Task> GetAllAsync() public async Task GetByIdAsync(string id) { var user = await _context.Users - .FirstOrDefaultAsync(x => x.Id == id); - - //var user = await _userManager.FindByIdAsync(id) - // ?? throw new EntityNotFoundException($"User with id : {id} is not found!"); + .FirstOrDefaultAsync(x => x.Id == id) + ?? throw new EntityNotFoundException(); UserDto userDto = _mapper.Map(user); + + if(user.ProfileImagePath is not null) + userDto.Image = await fileManaging.DownloadFileAsync(user.ProfileImagePath,"UserImages"); + return userDto; } @@ -58,6 +62,7 @@ public async Task CreateAsync(UserForCreateDto userCreateDto) return _mapper.Map(user); } + public async Task UpdateAsync(string id, UserForUpdatesDto userUpdateDto) { var user = await _userManager.FindByIdAsync(id) @@ -72,38 +77,43 @@ public async Task UpdateAsync(string id, UserForUpdatesDto userUpdateDto) { throw new InvalidOperationException($"Something wrong with updating user with id : {id}"); } - } + } public async Task DeleteAsync(string id) { - //var user = await _context.Users - // .FirstOrDefaultAsync(x => x.Id == id); - //if (user == null) - //{ - // return false; - //} - //_context.Users.Remove(user); - //await _context.SaveChangesAsync(); - //return true; try { var user = await _context.Users - .FirstOrDefaultAsync(x => x.Id == id); + .FirstOrDefaultAsync(x => x.Id == id); if (user == null) { return false; } + ///Manually deleting user answers because does not delete user with answers + var answers = await _context.Answers + .Where(a => a.UserId == user.Id) + .Select(a => a.Id) + .ToListAsync(); + + foreach(var ans in answers) + { + await _answerService.DeleteAsync(ans); + } _context.Users.Remove(user); - await _context.SaveChangesAsync(); + _context.SaveChanges(); + return true; } catch (Exception ex) { - // Xatolikni loglash - // _logger.LogError(ex, "Error occurred while deleting user."); throw; // Xatolikni yuqoriga qaytarish } } + + public async Task CreateImage(IFormFile file) + { + return await _fileManaging.UploadFile(file, "Source", "Images", "userImages"); + } } diff --git a/SciQuery.Service/Services/VoteService.cs b/SciQuery.Service/Services/VoteService.cs deleted file mode 100644 index 9f93b34..0000000 --- a/SciQuery.Service/Services/VoteService.cs +++ /dev/null @@ -1,71 +0,0 @@ -using AutoMapper; -using Microsoft.EntityFrameworkCore; -using SciQuery.Domain.Entities; -using SciQuery.Domain.Exceptions; -using SciQuery.Domain.UserModels; -using SciQuery.Infrastructure.Persistance.DbContext; -using SciQuery.Service.DTOs.Vote; -using SciQuery.Service.Interfaces; -using SciQuery.Service.Mappings.Extensions; -using SciQuery.Service.Pagination.PaginatedList; - -namespace SciQuery.Service.Services; - -public class VoteService(SciQueryDbContext context, IMapper mapper) : IVoteService -{ - private readonly SciQueryDbContext _context = context; - private readonly IMapper _mapper = mapper; - - - public async Task> GetAllVotesByQuestionIdAsync(int questionId) - { - var votes = await _context.Votes - .Include(x => x.User) - .Where(v => v.QuestionId == questionId) - .AsNoTracking() - .AsSplitQuery() - .ToPaginatedList(_mapper.ConfigurationProvider); - return votes; - } - public async Task> GetVoteByUserIdAsync(string userId) - { - var votes = await _context.Votes - .Include(x => x.User) - .Where(u => u.UserId == userId) - .AsNoTracking() - .AsSplitQuery() - .ToPaginatedList(_mapper.ConfigurationProvider); - - return votes; - } - - public async Task> GetAllVotesByAnswerIdAsync(int answerId) - { - var votes = await _context.Votes - .Where(v => v.AnswerId == answerId) - .AsNoTracking() - .AsSplitQuery() - .ToPaginatedList(_mapper.ConfigurationProvider); - return votes; - } - - public async Task CreateVoteAsync(VoteForCreateDto voteCreateDto) - { - var vote = _mapper.Map(voteCreateDto); - - _context.Votes.Add(vote); - await _context.SaveChangesAsync(); - - return _mapper.Map(vote); - } - - public async Task DeleteVoteAsync(int id) - { - var vote = await _context.Votes.FindAsync(id) - ?? throw new EntityNotFoundException($"Vote with id : {id} is not found!"); - - _context.Votes.Remove(vote); - await _context.SaveChangesAsync(); - return true; - } -} diff --git a/SciQuery/Controllers/AnswersController.cs b/SciQuery/Controllers/AnswersController.cs index eaf5c6a..c0cf9a7 100644 --- a/SciQuery/Controllers/AnswersController.cs +++ b/SciQuery/Controllers/AnswersController.cs @@ -1,15 +1,22 @@ -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using SciQuery.Domain.Entities; +using SciQuery.Domain.Exceptions; +using SciQuery.Domain.UserModels; using SciQuery.Service.DTOs.Answer; using SciQuery.Service.Interfaces; +using SciQuery.Service.Services; namespace SciQuery.Controllers { [Route("api/[controller]")] [ApiController] - public class AnswersController(IAnswerService answerService) : ControllerBase + public class AnswersController(IAnswerService answerService,UserManageruserManager) : ControllerBase { private readonly IAnswerService _answerService = answerService; + private readonly UserManager _userManager = userManager; [HttpGet("{id}")] public async Task GetAnswerById(int id) @@ -30,6 +37,7 @@ public async Task GetAllAnswersByQuestionId(int questionId) } [HttpPost] + [Authorize] public async Task CreateAnswer([FromBody] AnswerForCreateDto answerCreateDto) { if (!ModelState.IsValid) @@ -37,18 +45,41 @@ public async Task CreateAnswer([FromBody] AnswerForCreateDto answ return BadRequest(ModelState); } + // Foydalanuvchini topish + var user = await _userManager.GetUserAsync(User) + ?? throw new EntityNotFoundException("User does not found!"); + + answerCreateDto.UserId = user.Id; + var createdAnswer = await _answerService.CreateAsync(answerCreateDto); return CreatedAtAction(nameof(GetAnswerById), new { id = createdAnswer.Id }, createdAnswer); } + [HttpPost("upload-image")] + [Authorize] + public async Task UploadFile(IFormFile file) + { + var result = await _answerService.CreateImages(file); + return Ok(result); + } + + [HttpPut("{id}")] + [Authorize] public async Task UpdateAnswer(int id, [FromBody] AnswerForUpdateDto answerUpdateDto) { + if (!ModelState.IsValid) { return BadRequest(ModelState); } + // Foydalanuvchini topish + var user = await _userManager.GetUserAsync(User) + ?? throw new EntityNotFoundException("User does not found!"); + + answerUpdateDto.UserId = user.Id; + await _answerService.UpdateAsync(id, answerUpdateDto); return NoContent(); diff --git a/SciQuery/Controllers/CommentsController.cs b/SciQuery/Controllers/CommentsController.cs index de0a760..4c644b9 100644 --- a/SciQuery/Controllers/CommentsController.cs +++ b/SciQuery/Controllers/CommentsController.cs @@ -1,5 +1,9 @@ -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using SciQuery.Domain.Exceptions; +using SciQuery.Domain.UserModels; using SciQuery.Service.DTOs.Comment; using SciQuery.Service.Interfaces; @@ -7,9 +11,10 @@ namespace SciQuery.Controllers { [Route("api/[controller]")] [ApiController] - public class CommentsController(ICommentService commentService) : ControllerBase + public class CommentsController(ICommentService commentService, UserManager userManager) : ControllerBase { private readonly ICommentService _commentService = commentService; + private readonly UserManager _userManager = userManager; [HttpGet("{id}")] public async Task GetCommentById(int id) @@ -37,12 +42,18 @@ public async Task GetAllCommentsByAnswerId(int answerId) } [HttpPost] + [Authorize] public async Task CreateComment([FromBody] CommentForCreateDto commentCreateDto) { if (!ModelState.IsValid) { return BadRequest(ModelState); } + // Foydalanuvchini topish + var user = await _userManager.GetUserAsync(User) + ?? throw new EntityNotFoundException("User does not found!"); + + commentCreateDto.UserId = user.Id; var createdComment = await _commentService.CreateCommentAsync(commentCreateDto); return CreatedAtAction(nameof(GetCommentById), new { id = createdComment.Id }, createdComment); @@ -55,13 +66,15 @@ public async Task UpdateComment(int id, [FromBody] CommentForUpda { return BadRequest(ModelState); } + + // Foydalanuvchini topish + var user = await _userManager.GetUserAsync(User) + ?? throw new EntityNotFoundException("User does not found!"); - var updatedComment = await _commentService.UpdateCommentAsync(id, commentUpdateDto); - if (updatedComment == null) - { - return NotFound(); - } + commentUpdateDto.UserId = user.Id; + var updatedComment = await _commentService.UpdateCommentAsync(id, commentUpdateDto); + return Ok(updatedComment); } diff --git a/SciQuery/Controllers/ImagesController.cs b/SciQuery/Controllers/ImagesController.cs deleted file mode 100644 index cb13050..0000000 --- a/SciQuery/Controllers/ImagesController.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 - -namespace SciQuery.Controllers -{ - [Route("api/[controller]")] - [ApiController] - public class ImagesController : ControllerBase - { - // GET: api/ - [HttpGet] - public IEnumerable Get() - { - return new string[] { "value1", "value2" }; - } - - // GET api//5 - [HttpGet("{id}")] - public string Get(int id) - { - return "value"; - } - - // POST api/ - [HttpPost] - public void Post([FromBody] string value) - { - } - - // PUT api//5 - [HttpPut("{id}")] - public void Put(int id, [FromBody] string value) - { - } - - // DELETE api//5 - [HttpDelete("{id}")] - public void Delete(int id) - { - } - } -} diff --git a/SciQuery/Controllers/NotificationController.cs b/SciQuery/Controllers/NotificationController.cs new file mode 100644 index 0000000..1695d2e --- /dev/null +++ b/SciQuery/Controllers/NotificationController.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace SciQuery.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class NotificationController : ControllerBase + { + private readonly NotificationService _notificationService; + + public NotificationController(NotificationService notificationService) + { + _notificationService = notificationService; + } + + [HttpPost("send-notification")] + public async Task SendNotification(string userId, string message) + { + await _notificationService.NotifyUser(userId, message); + return Ok("Notification sent"); + } + } +} diff --git a/SciQuery/Controllers/QuestionsController.cs b/SciQuery/Controllers/QuestionsController.cs index 407d89c..29483fc 100644 --- a/SciQuery/Controllers/QuestionsController.cs +++ b/SciQuery/Controllers/QuestionsController.cs @@ -1,4 +1,3 @@ - using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Identity; @@ -9,107 +8,98 @@ using SciQuery.Service.Interfaces; using SciQuery.Service.QueryParams; using SciQuery.Service.Services; +using System.Security.Claims; -namespace SciQuery.Controllers +namespace SciQuery.Controllers; + +[Route("api/[controller]")] +[ApiController] +[EnableCors("AllowLocalhost5173")] +public class QuestionsController(IQuestionService questionService, UserManager userManager) : ControllerBase { - [Route("api/[controller]")] - [ApiController] - [EnableCors("AllowLocalhost5173")] - public class QuestionsController : ControllerBase + + private readonly IQuestionService _questionService = questionService; + private readonly UserManager _userManager = userManager; + + [HttpGet("get-with-tags")] + public async Task GetQuestionsByTags([FromBody] QuestionQueryParameters queryParameters) { - private readonly IQuestionService _questionService; - private readonly UserManager _userManager; + var result = await _questionService.GetQuestionsByTags(queryParameters); + return Ok(result); + } - public QuestionsController(IQuestionService questionService, UserManager userManager) - { - _questionService = questionService; - _userManager = userManager; - } + [HttpGet] + public async Task GetAllQuestions([FromQuery] QuestionQueryParameters queryParameters) + { + var questions = await _questionService.GetAllAsync(queryParameters); + return Ok(questions); + } - [HttpGet("get-with-tags")] - public async Task GetQuestionsByTags([FromBody] QuestionQueryParameters queryParameters) + [HttpGet("{id}")] + public async Task GetQuestionById(int id) + { + var question = await _questionService.GetByIdAsync(id); + if (question == null) { - var result = await _questionService.GetQuestionsByTags(queryParameters); - return Ok(result); + return NotFound(); } + return Ok(question); + } - [HttpGet] - public async Task GetAllQuestions([FromQuery] QuestionQueryParameters queryParameters) - { - var questions = await _questionService.GetAllAsync(queryParameters); - return Ok(questions); - } + [HttpPost] + [Authorize] + public async Task Post([FromBody] QuestionForCreateDto question) + { + // Foydalanuvchini topish + var user = await _userManager.GetUserAsync(User) + ?? throw new EntityNotFoundException("User does not found!"); + + question.UserId = user.Id; - [HttpGet("{id}")] - public async Task GetQuestionById(int id) + // ModelState ni tekshirish + if (!ModelState.IsValid) { - var question = await _questionService.GetByIdAsync(id); - if (question == null) - { - return NotFound(); - } - return Ok(question); + return BadRequest(ModelState); } - [HttpPost] - [Authorize] - public async Task CreateQuestion([FromBody] QuestionForCreateDto question) - { - // Foydalanuvchini topish - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - throw new EntityNotFoundException("User does not found!"); - } - - question.UserId = user.Id; - - // ModelState ni tekshirish - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - try - { - // Savol yaratish jarayoni - var createdQuestion = await _questionService.CreateAsync(question); - - // Yaratilgan savolni qaytarish - return CreatedAtAction(nameof(GetQuestionById), - new { id = createdQuestion.Id }, - createdQuestion); - } - catch (Exception ex) - { - // Har qanday boshqa xatolar uchun umumiy xatolik javobini qaytarish - return StatusCode(500, $"Internal server error: {ex.Message}"); - } - } + // Savol yaratish jarayoni + var createdQuestion = await _questionService.CreateAsync(question); - [HttpPut("{id}")] - public async Task UpdateQuestion(int id, [FromBody] QuestionForUpdateDto questionDto) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } + // Yaratilgan savolni qaytarish + return CreatedAtAction(nameof(GetQuestionById), + new { id = createdQuestion.Id }, createdQuestion); + } - await _questionService.UpdateAsync(id, questionDto); + [HttpPost("upload-image")] + [Authorize] + public async Task UploadFile( IFormFile file) + { + var result = await _questionService.CreateImages(file); + return Ok(result); + } - return NoContent(); + [HttpPut("{id}")] + public async Task UpdateQuestion(int id, [FromBody] QuestionForUpdateDto questionDto) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); } - [HttpDelete("{id}")] - public async Task DeleteQuestion(int id) - { - var result = await _questionService.DeleteAsync(id); - if (!result) - { - return NotFound(); - } + await _questionService.UpdateAsync(id, questionDto); + + return NoContent(); + } - return NoContent(); + [HttpDelete("{id}")] + public async Task DeleteQuestion(int id) + { + var result = await _questionService.DeleteAsync(id); + if (!result) + { + return NotFound(); } + + return NoContent(); } -} +} \ No newline at end of file diff --git a/SciQuery/Controllers/UsersController.cs b/SciQuery/Controllers/UsersController.cs index 3e18d2b..5bcb1ea 100644 --- a/SciQuery/Controllers/UsersController.cs +++ b/SciQuery/Controllers/UsersController.cs @@ -45,6 +45,14 @@ public async Task CreateUser([FromBody] UserForCreateDto userCrea return CreatedAtAction(nameof(GetUserById), new { id = createdUser.Id }, createdUser); } + [HttpPost("UploadImages")] + public async Task UploadFile(IFormFile file) + { + var result = await _userService.CreateImage(file); + return Ok(result); + } + + [HttpPut("{id}")] public async Task UpdateUser(string id, [FromBody] UserForUpdatesDto userUpdateDto) @@ -56,7 +64,7 @@ public async Task UpdateUser(string id, [FromBody] UserForUpdates await _userService.UpdateAsync(id, userUpdateDto); - return Ok(); + return NoContent(); } [HttpDelete("{id}")] diff --git a/SciQuery/Controllers/VotesController.cs b/SciQuery/Controllers/VotesController.cs deleted file mode 100644 index fc4642a..0000000 --- a/SciQuery/Controllers/VotesController.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using SciQuery.Service.DTOs.Vote; -using SciQuery.Service.Interfaces; - -namespace SciQuery.Controllers -{ - [Route("api/[controller]")] - [ApiController] - public class VotesController(IVoteService voteService) : ControllerBase - { - private readonly IVoteService _voteService = voteService; - - [HttpGet("user/{id}")] - public async Task GetVoteByUserId(string id) - { - var vote = await _voteService.GetVoteByUserIdAsync(id); - if (vote == null) - { - return NotFound(); - } - return Ok(vote); - } - - [HttpGet("question/{questionId}")] - public async Task GetAllVotesByQuestionId(int questionId) - { - var votes = await _voteService.GetAllVotesByQuestionIdAsync(questionId); - return Ok(votes); - } - - [HttpGet("answer/{answerId}")] - public async Task GetAllVotesByAnswerId(int answerId) - { - var votes = await _voteService.GetAllVotesByAnswerIdAsync(answerId); - return Ok(votes); - } - - [HttpPost] - public async Task CreateVote([FromBody] VoteForCreateDto voteCreateDto) - { - if (!ModelState.IsValid) - { - return BadRequest(ModelState); - } - - var createdVote = await _voteService.CreateVoteAsync(voteCreateDto); - return Ok(); - } - - [HttpDelete("{id}")] - public async Task DeleteVote(int id) - { - var result = await _voteService.DeleteVoteAsync(id); - if (!result) - { - return NotFound(); - } - - return NoContent(); - } - } -} diff --git a/SciQuery/Extension/DatabaseSeeder.cs b/SciQuery/Extension/DatabaseSeeder.cs index d42281e..a6ce26b 100644 --- a/SciQuery/Extension/DatabaseSeeder.cs +++ b/SciQuery/Extension/DatabaseSeeder.cs @@ -23,152 +23,140 @@ public static void SeedData(SciQueryDbContext context) context.SaveChanges(); AddTags(context); - context.SaveChanges(); + context.SaveChanges(); AddQuestionTags(context); - context.SaveChanges(); - - AddVotes(context); context.SaveChanges(); AddReputationChanges(context); - context.SaveChanges(); + context.SaveChanges(); } catch (Exception ex) { - Console.WriteLine(ex.Message); - throw; + { + Console.WriteLine(ex.Message); + throw; + } + } } + + private static void AddUsers(SciQueryDbContext context) + { + if (context.Users.Any()) return; + // User generation + var userFaker = new Faker() + .RuleFor(u => u.Id, f => Guid.NewGuid().ToString()) + .RuleFor(u => u.UserName, f => f.Internet.UserName()) + .RuleFor(u => u.Email, f => f.Internet.Email()) + .RuleFor(u => u.ProfileImagePath, f => f.Internet.Avatar()) + .RuleFor(u => u.Reputation, f => f.Random.Int(0, 1000)) + .RuleFor(u => u.CreatedDate, f => f.Date.Past(5)) + .RuleFor(u => u.LastLogindate, f => f.Date.Recent()); + + var users = userFaker.Generate(10); // 10 users + context.Users.AddRange(users); } - } - private static void AddUsers(SciQueryDbContext context) - { - if (context.Users.Any()) return; - // User generation - var userFaker = new Faker() - .RuleFor(u => u.Id, f => Guid.NewGuid().ToString()) - .RuleFor(u => u.UserName, f => f.Internet.UserName()) - .RuleFor(u => u.Email, f => f.Internet.Email()) - .RuleFor(u => u.ProfileImagePath, f => f.Internet.Avatar()) - .RuleFor(u => u.Reputation, f => f.Random.Int(0, 1000)) - .RuleFor(u => u.CreatedDate, f => f.Date.Past(5)) - .RuleFor(u => u.LastLogindate, f => f.Date.Recent()); - - var users = userFaker.Generate(10); // 10 users - context.Users.AddRange(users); - } - - private static void AddQuestions(SciQueryDbContext context) - { - if (context.Questions.Any()) return; - var userIds = context.Users.Select(u => u.Id).ToList(); // Get user IDs + private static void AddQuestions(SciQueryDbContext context) + { + if (context.Questions.Any()) return; + var userIds = context.Users.Select(u => u.Id).ToList(); // Get user IDs + + var questionFaker = new Faker() + .RuleFor(q => q.UserId, f => f.PickRandom(userIds)) + .RuleFor(q => q.Title, f => f.Lorem.Sentence()) + .RuleFor(q => q.Body, f => f.Lorem.Paragraphs()) + .RuleFor(q => q.CreatedDate, f => f.Date.Past()) + .RuleFor(q => q.UpdatedDate, f => f.Date.Past()); + + var questions = questionFaker.Generate(50); // 20 questions + context.Questions.AddRange(questions); + } - var questionFaker = new Faker() - .RuleFor(q => q.UserId, f => f.PickRandom(userIds)) - .RuleFor(q => q.Title, f => f.Lorem.Sentence()) - .RuleFor(q => q.Body, f => f.Lorem.Paragraphs()) - .RuleFor(q => q.CreatedDate, f => f.Date.Past()) - .RuleFor(q => q.UpdatedDate, f => f.Date.Past()); + private static void AddAnswers(SciQueryDbContext context) + { + if (context.Answers.Any()) return; + var questionIds = context.Questions.Select(q => q.Id).ToList(); + var userIds = context.Users.Select(u => u.Id).ToList(); + + var answerFaker = new Faker() + .RuleFor(a => a.QuestionId, f => f.PickRandom(questionIds)) + .RuleFor(a => a.UserId, f => f.PickRandom(userIds)) + .RuleFor(a => a.Body, f => f.Lorem.Paragraphs()) + .RuleFor(a => a.CreatedDate, f => f.Date.Past()) + .RuleFor(a => a.UpdatedDate, f => f.Date.Past()); + + var answers = answerFaker.Generate(50); // 50 answers + context.Answers.AddRange(answers); + } - var questions = questionFaker.Generate(20); // 20 questions - context.Questions.AddRange(questions); - } + private static void AddComments(SciQueryDbContext context) + { + if (context.Comments.Any()) return; + var userIds = context.Users.Select(u => u.Id).ToList(); + var questionIds = context.Questions.Select(q => q.Id).ToList(); + var answerIds = context.Answers.Select(a => a.Id).ToList(); + + var commentFaker = new Faker() + .RuleFor(c => c.UserId, f => f.PickRandom(userIds)) + .RuleFor(c => c.PostId, f => f.PickRandom(questionIds)) + .RuleFor(c => c.Body, f => f.Lorem.Paragraphs()) + .RuleFor(c => c.CreatedDate, f => f.Date.Past()); + + var commentFakerAnswer = new Faker() + .RuleFor(c => c.UserId, f => f.PickRandom(userIds)) + .RuleFor(c => c.PostId, f => f.PickRandom(answerIds)) + .RuleFor(c => c.Body, f => f.Lorem.Paragraphs()) + .RuleFor(c => c.CreatedDate, f => f.Date.Past()); + + var comments = commentFaker.Generate(100); // 100 comments + var commentsAnswer = commentFakerAnswer.Generate(100); // 100 comments + + for (int i = 0; i < 100; i++) + { + comments[i].Post = PostType.Question; + commentsAnswer[i].Post = PostType.Answer; + } + + context.Comments.AddRange(comments); + context.Comments.AddRange(commentsAnswer); + } - private static void AddAnswers(SciQueryDbContext context) - { - if (context.Answers.Any()) return; - var questionIds = context.Questions.Select(q => q.Id).ToList(); - var userIds = context.Users.Select(u => u.Id).ToList(); - - var answerFaker = new Faker() - .RuleFor(a => a.QuestionId, f => f.PickRandom(questionIds)) - .RuleFor(a => a.UserId, f => f.PickRandom(userIds)) - .RuleFor(a => a.Body, f => f.Lorem.Paragraphs()) - .RuleFor(a => a.CreatedDate, f => f.Date.Past()) - .RuleFor(a => a.UpdatedDate, f => f.Date.Past()); - - var answers = answerFaker.Generate(50); // 50 answers - context.Answers.AddRange(answers); - } - - private static void AddComments(SciQueryDbContext context) - { - if (context.Comments.Any()) return; - var userIds = context.Users.Select(u => u.Id).ToList(); - var questionIds = context.Questions.Select(q => q.Id).ToList(); - var answerIds = context.Answers.Select(a => a.Id).ToList(); - - var commentFaker = new Faker() - .RuleFor(c => c.UserId, f => f.PickRandom(userIds)) - .RuleFor(c => c.QuestionId, f => f.PickRandom(questionIds)) - .RuleFor(c => c.Body, f => f.Lorem.Paragraphs()) - .RuleFor(c => c.CreatedDate, f => f.Date.Past()); - - var commentFakerAnswer = new Faker() - .RuleFor(c => c.UserId, f => f.PickRandom(userIds)) - .RuleFor(c => c.AnswerId, f => f.PickRandom(answerIds)) - .RuleFor(c => c.Body, f => f.Lorem.Paragraphs()) - .RuleFor(c => c.CreatedDate, f => f.Date.Past()); - - var comments = commentFaker.Generate(100); // 100 comments - var commentsAnswer = commentFakerAnswer.Generate(100); // 100 comments - context.Comments.AddRange(comments); - context.Comments.AddRange(commentsAnswer); - } - - private static void AddTags(SciQueryDbContext context) - { - if (context.Tags.Any()) return; - var tagFaker = new Faker() - .RuleFor(t => t.Name, f => f.Lorem.Word()); + private static void AddTags(SciQueryDbContext context) + { + if (context.Tags.Any()) return; + var tagFaker = new Faker() + .RuleFor(t => t.Name, f => f.Lorem.Word()); - var tags = tagFaker.Generate(15); // 15 tags - context.Tags.AddRange(tags); - } + var tags = tagFaker.Generate(50); // 15 tags + context.Tags.AddRange(tags); + } - private static void AddQuestionTags(SciQueryDbContext context) - { - if (context.QuestionTags.Any()) return; - var questionIds = context.Questions.Select(q => q.Id).ToList(); - var tagIds = context.Tags.Select(t => t.Id).ToList(); + private static void AddQuestionTags(SciQueryDbContext context) + { + if (context.QuestionTags.Any()) return; + var questionIds = context.Questions.Select(q => q.Id).ToList(); + var tagIds = context.Tags.Select(t => t.Id).ToList(); - var questionTagFaker = new Faker() - .RuleFor(qt => qt.QuestionId, f => f.PickRandom(questionIds)) - .RuleFor(qt => qt.TagId, f => f.PickRandom(tagIds)); + var questionTagFaker = new Faker() + .RuleFor(qt => qt.QuestionId, f => f.PickRandom(questionIds)) + .RuleFor(qt => qt.TagId, f => f.PickRandom(tagIds)); - var questionTags = questionTagFaker.Generate(30); // 30 question tags - context.QuestionTags.AddRange(questionTags); - } + var questionTags = questionTagFaker.Generate(100); // 50 question tags + context.QuestionTags.AddRange(questionTags); + } - private static void AddVotes(SciQueryDbContext context) - { - if (context.Votes.Any()) return; - var userIds = context.Users.Select(u => u.Id).ToList(); - var questionIds = context.Questions.Select(q => q.Id).ToList(); - var answerIds = context.Answers.Select(a => a.Id).ToList(); - - var voteFaker = new Faker() - .RuleFor(v => v.UserId, f => f.PickRandom(userIds)) - .RuleFor(v => v.QuestionId, f => f.PickRandom(questionIds)) - .RuleFor(v => v.AnswerId, f => f.PickRandom(answerIds)) - .RuleFor(v => v.VoteType, f => f.PickRandom()); - - var votes = voteFaker.Generate(50); // 50 ta vote ma'lumotlari - context.Votes.AddRange(votes); - } - - private static void AddReputationChanges(SciQueryDbContext context) - { - if (context.ReputationChanges.Any()) return; - var userIds = context.Users.Select(u => u.Id).ToList(); - - var reputationChangeFaker = new Faker() - .RuleFor(rc => rc.UserId, f => f.PickRandom(userIds)) - .RuleFor(rc => rc.ChangeAmount, f => f.Random.Int(-100, 100)) - .RuleFor(rc => rc.Reason, f => f.Lorem.Sentence()) - .RuleFor(rc => rc.CreatedDate, f => f.Date.Past()); - - var reputationChanges = reputationChangeFaker.Generate(30); // 30 ta ma'lumot - context.ReputationChanges.AddRange(reputationChanges); - } -} + private static void AddReputationChanges(SciQueryDbContext context) + { + if (context.ReputationChanges.Any()) return; + var userIds = context.Users.Select(u => u.Id).ToList(); + + var reputationChangeFaker = new Faker() + .RuleFor(rc => rc.UserId, f => f.PickRandom(userIds)) + .RuleFor(rc => rc.ChangeAmount, f => f.Random.Int(-100, 100)) + .RuleFor(rc => rc.Reason, f => f.Lorem.Sentence()) + .RuleFor(rc => rc.CreatedDate, f => f.Date.Past()); + + var reputationChanges = reputationChangeFaker.Generate(30); // 30 ta ma'lumot + context.ReputationChanges.AddRange(reputationChanges); + } + } diff --git a/SciQuery/Program.cs b/SciQuery/Program.cs index ad09567..0cfc0da 100644 --- a/SciQuery/Program.cs +++ b/SciQuery/Program.cs @@ -1,6 +1,6 @@ -using Bogus; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.StaticFiles; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using SciQuery.Domain.UserModels; @@ -30,15 +30,19 @@ builder.Services.AddControllers(); +builder.Services.AddSingleton(); + //Add Services +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(UserMappings).Assembly); + + //Identity Usermanager and rolemanager builder.Services.AddDbContext(); @@ -105,12 +109,13 @@ { options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { - Description = "Jwt authorization header using the Bearer scheme. Example :\"Authorization : Bearer {token}\"", - Name = "Authoriation", + Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", + Name = "Authorization", // Corrected from "Authoriation" In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement { { @@ -119,13 +124,15 @@ Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, - Id = "Bearer", - } - } - ,new string[]{} + Id = "Bearer" + }, + Scheme = "oauth2", + Name = "Bearer", + In = ParameterLocation.Header + }, + new string[] {} } }); - }); //Policies for Role requirements @@ -146,9 +153,14 @@ builder => builder .WithOrigins("http://localhost:5173") .AllowAnyHeader() - .AllowAnyMethod()); + .AllowAnyMethod() + .AllowCredentials()); }); +builder.Services.AddScoped(); +builder.Services.AddSignalR(); + + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -176,6 +188,7 @@ if (!await roleManager.RoleExistsAsync(AppRoles.User)) { await roleManager.CreateAsync(new IdentityRole(AppRoles.User)); + await roleManager.CreateAsync(new IdentityRole(AppRoles.User)); } if (!await roleManager.RoleExistsAsync(AppRoles.Administrator)) @@ -202,6 +215,8 @@ app.UseAuthorization(); +app.MapHub("api/notificationHub"); + app.MapControllers(); app.Run(); diff --git a/SciQuery/SciQuery.csproj b/SciQuery/SciQuery.csproj index 8ba392e..ce349fd 100644 --- a/SciQuery/SciQuery.csproj +++ b/SciQuery/SciQuery.csproj @@ -9,6 +9,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -17,7 +18,7 @@ - + @@ -26,8 +27,10 @@ - - + + + + diff --git a/SciQuery/Source/Images/AnswerImages/2a6c01f7-2fbf-4127-96db-9be38fe65fd1maxresdefault.jpg b/SciQuery/Source/Images/AnswerImages/2a6c01f7-2fbf-4127-96db-9be38fe65fd1maxresdefault.jpg new file mode 100644 index 0000000..c008104 Binary files /dev/null and b/SciQuery/Source/Images/AnswerImages/2a6c01f7-2fbf-4127-96db-9be38fe65fd1maxresdefault.jpg differ diff --git a/SciQuery/Source/Images/AnswerImages/401c7fdc-26e6-4b0b-a63b-881873debe14photo_2024-08-03_19-36-06.jpg b/SciQuery/Source/Images/AnswerImages/401c7fdc-26e6-4b0b-a63b-881873debe14photo_2024-08-03_19-36-06.jpg new file mode 100644 index 0000000..4d760de Binary files /dev/null and b/SciQuery/Source/Images/AnswerImages/401c7fdc-26e6-4b0b-a63b-881873debe14photo_2024-08-03_19-36-06.jpg differ diff --git a/SciQuery/Source/Images/AnswerImages/bc8c36d1-9ed0-4cc9-b10d-f6a57019ec9cWIN_20240729_15_51_03_Pro.jpg b/SciQuery/Source/Images/AnswerImages/bc8c36d1-9ed0-4cc9-b10d-f6a57019ec9cWIN_20240729_15_51_03_Pro.jpg new file mode 100644 index 0000000..538c6ae Binary files /dev/null and b/SciQuery/Source/Images/AnswerImages/bc8c36d1-9ed0-4cc9-b10d-f6a57019ec9cWIN_20240729_15_51_03_Pro.jpg differ diff --git a/SciQuery/Source/Images/AnswerImages/ccb43493-5bef-4ca2-b64c-e0e709d09dfcphoto_2023-03-28_21-22-17.jpg b/SciQuery/Source/Images/AnswerImages/ccb43493-5bef-4ca2-b64c-e0e709d09dfcphoto_2023-03-28_21-22-17.jpg new file mode 100644 index 0000000..0846aee Binary files /dev/null and b/SciQuery/Source/Images/AnswerImages/ccb43493-5bef-4ca2-b64c-e0e709d09dfcphoto_2023-03-28_21-22-17.jpg differ diff --git a/SciQuery/Source/Images/QuestionImages/743391a9-d379-4469-b5c3-5afe1cba5bd5Screenshot 2024-07-06 000038.png b/SciQuery/Source/Images/QuestionImages/743391a9-d379-4469-b5c3-5afe1cba5bd5Screenshot 2024-07-06 000038.png new file mode 100644 index 0000000..b5c3a4b Binary files /dev/null and b/SciQuery/Source/Images/QuestionImages/743391a9-d379-4469-b5c3-5afe1cba5bd5Screenshot 2024-07-06 000038.png differ diff --git a/SciQuery/Source/Images/QuestionImages/f8dbb3f4-e710-4bb4-921c-59a2e720d166Screenshot 2024-07-05 211629.png b/SciQuery/Source/Images/QuestionImages/f8dbb3f4-e710-4bb4-921c-59a2e720d166Screenshot 2024-07-05 211629.png new file mode 100644 index 0000000..cf8c08d Binary files /dev/null and b/SciQuery/Source/Images/QuestionImages/f8dbb3f4-e710-4bb4-921c-59a2e720d166Screenshot 2024-07-05 211629.png differ diff --git a/SciQuery/Source/Images/userImages/cf848da0-5a56-493c-aefd-33292b10c5d0photo_2024-08-03_19-36-06.jpg b/SciQuery/Source/Images/userImages/cf848da0-5a56-493c-aefd-33292b10c5d0photo_2024-08-03_19-36-06.jpg new file mode 100644 index 0000000..4d760de Binary files /dev/null and b/SciQuery/Source/Images/userImages/cf848da0-5a56-493c-aefd-33292b10c5d0photo_2024-08-03_19-36-06.jpg differ diff --git a/SciQuery/Source/Images/userImages/d98ede72-8a31-41b8-9553-a11c6761187ephoto_2024-08-03_19-36-06.jpg b/SciQuery/Source/Images/userImages/d98ede72-8a31-41b8-9553-a11c6761187ephoto_2024-08-03_19-36-06.jpg new file mode 100644 index 0000000..4d760de Binary files /dev/null and b/SciQuery/Source/Images/userImages/d98ede72-8a31-41b8-9553-a11c6761187ephoto_2024-08-03_19-36-06.jpg differ diff --git a/SciQuery/appsettings.json b/SciQuery/appsettings.json index c1cd000..9b0d304 100644 --- a/SciQuery/appsettings.json +++ b/SciQuery/appsettings.json @@ -12,8 +12,8 @@ "ValidAudiences": "https://localhost:7190/" }, "ConnectionStrings": { - "DefaultConnectionMuhammad": "Data Source=muhammad2256\\sqlexpress;Initial Catalog=SciDb;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True", - "DefaultConnectionFirdavs": "Data Source=DESKTOP-UVO0SDG;Initial Catalog=SciQuery;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True", - "DefaultConnectionJavlon": "Data Source=ALIMOV\\SQLEXPRESS;Initial Catalog=SciQueryDb;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True" + "DefaultConnectionMuhammad": "Data Source=muhammad2256\\sqlexpress;Initial Catalog=SciQuery;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True", + "DefaultConnectionJavlon": "Data Source=alimov\\sqlexpress;Initial Catalog=SciQueryDb;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True", + "DefaultConnectionFirdavs": "Data Source=DESKTOP-UVO0SDG;Initial Catalog=Testing;Integrated Security=True;Pooling=False;Encrypt=True;Trust Server Certificate=True" } }