From d9a0d528be3c56faa88779e3f1d2a61ede4a16d3 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:53:40 +0300 Subject: [PATCH 01/56] Add migrations --- .../20250423104019_Init.Designer.cs | 415 ++++++++++++++++++ .../Migrations/20250423104019_Init.cs | 294 +++++++++++++ .../Migrations/MyDbContextModelSnapshot.cs | 412 +++++++++++++++++ 3 files changed, 1121 insertions(+) create mode 100644 MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250423104019_Init.cs create mode 100644 MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs diff --git a/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs b/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs new file mode 100644 index 0000000..13b7cb8 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250423104019_Init.Designer.cs @@ -0,0 +1,415 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250423104019_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("additionalInfo"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("endDate"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prize") + .HasColumnType("numeric") + .HasColumnName("prize"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("startDate"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackthonTag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("LinkToWebSite") + .IsRequired() + .HasColumnType("text") + .HasColumnName("linkToWebsite"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("TrackAdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackAdditionalInfo"); + + b.Property("TrackName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackName"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("track", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Surname") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tracks") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + + b.Navigation("Tracks"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs b/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs new file mode 100644 index 0000000..6f0dcd2 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250423104019_Init.cs @@ -0,0 +1,294 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "mainSchema"); + + migrationBuilder.CreateTable( + name: "organization", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + description = table.Column(type: "text", nullable: false), + linkToWebsite = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_organization", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "tag", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + tagName = table.Column(type: "text", nullable: false), + tagClassName = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_tag", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "teamMember", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + birthDate = table.Column(type: "timestamp with time zone", nullable: false), + education = table.Column(type: "text", nullable: false), + firstName = table.Column(type: "text", nullable: false), + lastName = table.Column(type: "text", nullable: false), + middleName = table.Column(type: "text", nullable: false), + userName = table.Column(type: "text", nullable: false), + Telegram = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_teamMember", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "hackathon", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + organizationId = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + prize = table.Column(type: "numeric", nullable: false), + minTeamSize = table.Column(type: "integer", nullable: false), + maxTeamSize = table.Column(type: "integer", nullable: false), + startDate = table.Column(type: "timestamp with time zone", nullable: false), + endDate = table.Column(type: "timestamp with time zone", nullable: false), + additionalInfo = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_hackathon", x => x.id); + table.ForeignKey( + name: "FK_hackathon_organization_organizationId", + column: x => x.organizationId, + principalSchema: "mainSchema", + principalTable: "organization", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "userTag", + schema: "mainSchema", + columns: table => new + { + userId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_userTag", x => new { x.tagId, x.userId }); + table.ForeignKey( + name: "FK_userTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_userTag_teamMember_userId", + column: x => x.userId, + principalSchema: "mainSchema", + principalTable: "teamMember", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "hackthonTag", + columns: table => new + { + hackathonId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_hackthonTag", x => new { x.tagId, x.hackathonId }); + table.ForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_hackthonTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "team", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "text", nullable: false), + description = table.Column(type: "text", nullable: false), + captainId = table.Column(type: "uuid", nullable: false), + teamCreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_team", x => x.id); + table.ForeignKey( + name: "FK_team_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "track", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + trackName = table.Column(type: "text", nullable: false), + trackAdditionalInfo = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_track", x => x.id); + table.ForeignKey( + name: "FK_track_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "userTeam", + schema: "mainSchema", + columns: table => new + { + userId = table.Column(type: "uuid", nullable: false), + teamId = table.Column(type: "uuid", nullable: false), + joinedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_userTeam", x => new { x.userId, x.teamId }); + table.ForeignKey( + name: "FK_userTeam_teamMember_userId", + column: x => x.userId, + principalSchema: "mainSchema", + principalTable: "teamMember", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_userTeam_team_teamId", + column: x => x.teamId, + principalSchema: "mainSchema", + principalTable: "team", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_hackathon_organizationId", + schema: "mainSchema", + table: "hackathon", + column: "organizationId"); + + migrationBuilder.CreateIndex( + name: "IX_hackthonTag_hackathonId", + table: "hackthonTag", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_team_hackathonId", + schema: "mainSchema", + table: "team", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_track_hackathonId", + schema: "mainSchema", + table: "track", + column: "hackathonId"); + + migrationBuilder.CreateIndex( + name: "IX_userTag_userId", + schema: "mainSchema", + table: "userTag", + column: "userId"); + + migrationBuilder.CreateIndex( + name: "IX_userTeam_teamId", + schema: "mainSchema", + table: "userTeam", + column: "teamId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "hackthonTag"); + + migrationBuilder.DropTable( + name: "track", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "userTag", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "userTeam", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "tag", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "teamMember", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "team", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "hackathon", + schema: "mainSchema"); + + migrationBuilder.DropTable( + name: "organization", + schema: "mainSchema"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs new file mode 100644 index 0000000..28f56a3 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -0,0 +1,412 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + partial class MyDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("additionalInfo"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("endDate"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prize") + .HasColumnType("numeric") + .HasColumnName("prize"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("startDate"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackthonTag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("LinkToWebSite") + .IsRequired() + .HasColumnType("text") + .HasColumnName("linkToWebsite"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("TrackAdditionalInfo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackAdditionalInfo"); + + b.Property("TrackName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trackName"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("track", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Surname") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("Telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tracks") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + + b.Navigation("Tracks"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} From f12b699a928ef080659d3e31e60859b291fd655d Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:54:32 +0300 Subject: [PATCH 02/56] Rename Db Context --- .../Data/{TeamDbContext.cs => MyDbContext.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MethodologyMain.Persistence/Data/{TeamDbContext.cs => MyDbContext.cs} (100%) diff --git a/MethodologyMain.Persistence/Data/TeamDbContext.cs b/MethodologyMain.Persistence/Data/MyDbContext.cs similarity index 100% rename from MethodologyMain.Persistence/Data/TeamDbContext.cs rename to MethodologyMain.Persistence/Data/MyDbContext.cs From 582a8820728c50e9a3d15ccfe3ef8de0e1093c23 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:56:08 +0300 Subject: [PATCH 03/56] Fix Team Repository to include team members --- .../Repository/TeamRepository.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index 0ea85d4..1188b0a 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -15,7 +15,7 @@ public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CheckCancellation(token); var user = await _context.Users .AsNoTracking() - .FirstAsync(e => e.Id == userId, token); + .FirstOrDefaultAsync(e => e.Id == userId, token); return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; } public async Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token) @@ -44,6 +44,7 @@ public async Task RemoveTeamAsync(Guid teamId, CancellationToken token) var team = await GetTeamAsync(teamId, token); if (team.Members is not null) { var _ = team.Members.RemoveAll; } _context.Teams.Remove(team); + await SaveChangesAsync(token); } public async Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token) @@ -75,6 +76,12 @@ public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, Cancellat var team = await GetTeamAsync(teamId, token); return team.Members.Select(m => m.UserId).ToList(); } + public async Task UpdateTeamAsync(TeamEntity team, CancellationToken token) + { + CheckCancellation(token); + _context.Update(team); + await _context.SaveChangesAsync(token); + } private static void CheckCancellation(CancellationToken token) { token.ThrowIfCancellationRequested(); @@ -82,14 +89,14 @@ private static void CheckCancellation(CancellationToken token) private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); - return await _context.Teams + return await _context.Teams.Include(m => m.Members) .AsNoTracking() - .FirstAsync(e => e.Id == teamId, token); + .FirstOrDefaultAsync(e => e.Id == teamId, token); } private async Task GetTeamAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); - return await _context.Teams.FindAsync([teamId], token); + return await _context.Teams.Include(m => m.Members).FirstOrDefaultAsync(m => m.Id == teamId); } private async Task SaveChangesAsync(CancellationToken token) { From 5d7323550024d2925e0ed48c3a45263c46b19bfb Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:57:00 +0300 Subject: [PATCH 04/56] Make General Repository async --- .../Interfaces/IGenericRepository.cs | 6 +++--- .../Repository/GenericRepository.cs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs index d6afcd6..137a296 100644 --- a/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IGenericRepository.cs @@ -4,11 +4,11 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IGenericRepository where T : class { + Task GetByIdAsync(Guid id, CancellationToken token); + Task> GetAllAsync(CancellationToken token); + Task> FindAsync(Expression> expression, CancellationToken token); Task AddAsync(T entity, CancellationToken token); Task AddRangeAsync(IEnumerable entities, CancellationToken token); - Task> FindAsync(Expression> expression, CancellationToken token); - Task> GetAllAsync(CancellationToken token); - Task GetByIdAsync(Guid id, CancellationToken token); Task RemoveAsync(T entity, CancellationToken token); Task RemoveRangeAsync(IEnumerable entities, CancellationToken token); } diff --git a/MethodologyMain.Persistence/Repository/GenericRepository.cs b/MethodologyMain.Persistence/Repository/GenericRepository.cs index 8b57920..43f0393 100644 --- a/MethodologyMain.Persistence/Repository/GenericRepository.cs +++ b/MethodologyMain.Persistence/Repository/GenericRepository.cs @@ -15,13 +15,13 @@ public GenericRepository(MyDbContext context) public async Task AddAsync(T entity, CancellationToken token) { - _context.Set().Add(entity); + await _context.Set().AddAsync(entity, token); await _context.SaveChangesAsync(token); } public async Task AddRangeAsync(IEnumerable entities, CancellationToken token) { - _context.Set().AddRange(entities); + await _context.Set().AddRangeAsync(entities, token); await _context.SaveChangesAsync(token); } @@ -32,12 +32,12 @@ public async Task> FindAsync(Expression> expression public async Task> GetAllAsync(CancellationToken token) { - return await _context.Set().ToListAsync(token); + return await _context.Set().AsNoTracking().ToListAsync(token); } public async Task GetByIdAsync(Guid id, CancellationToken token) { - return await _context.Set().FindAsync([id], token); + return await _context.Set().FindAsync(id, token); } public async Task RemoveAsync(T entity, CancellationToken token) From 33c99d74a08e5d1b7b8fa6f93cd12a422d0d8024 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:58:17 +0300 Subject: [PATCH 05/56] Add Update to Team Service --- .../Interface/ITeamService.cs | 3 +-- .../Services/TeamService.cs | 24 ++++++++++++++++--- .../Interfaces/ITeamRepository.cs | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index b5480b3..a0cb0f7 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,5 +1,4 @@ using MethodologyMain.Logic.Entities; -using MethodTeams.DTO; namespace MethodologyMain.Application.Interface { @@ -10,7 +9,7 @@ public interface ITeamService Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); Task GetTeamByIdAsync(Guid teamId, CancellationToken token); Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); - Task> GetTeamAllAsync(CancellationToken token); + Task> GetTeamAllAsync(CancellationToken token); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index dfeb4a7..9d1dfff 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -70,6 +70,23 @@ public async Task DeleteTeamAsync( await teamRepo.RemoveTeamAsync(teamId, token); } + public async Task UpdateTeamAsync( + Guid teamId, + Team team, + Guid requestingUserId, + CancellationToken token, + bool isAdmin = false + ) + { + await validation.CheckTeamExistsAsync(teamId, token); + await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + var teamEntity = await teamRepo.GetByIdAsync(teamId, token); + teamEntity.Description = team.Description; + teamEntity.Name = team.Name; + teamEntity.HackathonId = team.HackathonId; + await teamRepo.UpdateTeamAsync(teamEntity, token); + } + // Добавление пользователя в команду public async Task AddUserToTeamAsync( Guid teamId, @@ -129,11 +146,12 @@ public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken } // Получение списка команд - public async Task> GetTeamAllAsync(CancellationToken token) + public async Task> GetTeamAllAsync(CancellationToken token) { - + var teams = await teamRepo.GetAllAsync(token); - return mapper.Map>(teams); + //return mapper.Map>(teams); + return teams.ToList(); } //// Проверка, является ли пользователь капитаном команды diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index ed7d7b7..329d4e3 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -11,6 +11,7 @@ public interface ITeamRepository : IGenericRepository Task GetCaptainIdAsync(Guid teamId, CancellationToken token); Task GetHackathonIdAsync(Guid teamId, CancellationToken token); Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task UpdateTeamAsync(TeamEntity team, CancellationToken token); Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token); Task RemoveTeamAsync(Guid teamId, CancellationToken token); Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, CancellationToken token); From 9d5636401aaf1433990f9281aef9a95aa48ef668 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:58:45 +0300 Subject: [PATCH 06/56] Add User Controller --- .../Controllers/UserController.cs | 44 +++++++++++ .../Interface/IUserService.cs | 18 +++++ .../Services/UserService.cs | 79 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 MethodologyMain.API/Controllers/UserController.cs create mode 100644 MethodologyMain.Application/Interface/IUserService.cs create mode 100644 MethodologyMain.Application/Services/UserService.cs diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs new file mode 100644 index 0000000..109aa8a --- /dev/null +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -0,0 +1,44 @@ +using MethodologyMain.Application.DTO; +using MethodTeams.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Security.Claims; +using MethodologyMain.Application.Interface; +using AuthMetodology.Infrastructure.Interfaces; +using AuthMetodology.Infrastructure.Models; +using Serilog.Events; + +namespace MethodologyMain.API.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class UserController : ControllerBase + { + private readonly ITeamService teamService; + private readonly ILogQueueService logQueueService; + public UserController(ITeamService teamService, ILogQueueService logQueueService) + { + this.teamService = teamService; + this.logQueueService = logQueueService; + } + [HttpPost] + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) + { + _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "POST api/User was called", + TimeStamp = DateTime.UtcNow + }); + Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена + var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(team); + } + + private Guid GetCurrentUserId() + { + return Guid.Parse("1"); + } + } +} diff --git a/MethodologyMain.Application/Interface/IUserService.cs b/MethodologyMain.Application/Interface/IUserService.cs new file mode 100644 index 0000000..842b11e --- /dev/null +++ b/MethodologyMain.Application/Interface/IUserService.cs @@ -0,0 +1,18 @@ +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; + +namespace MethodologyMain.Application.Interface +{ + public interface IUserService + { + Task CreateUserAsync( + string UserName, + string description, + Guid captainId, + DateTime BirthDate, + CancellationToken token + ); + + } +} diff --git a/MethodologyMain.Application/Services/UserService.cs b/MethodologyMain.Application/Services/UserService.cs new file mode 100644 index 0000000..c28571f --- /dev/null +++ b/MethodologyMain.Application/Services/UserService.cs @@ -0,0 +1,79 @@ +using AutoMapper; +using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; +using MethodologyMain.Persistence.Interfaces; + +namespace MethodologyMain.Application.Services +{ + class UserService + { + private readonly IUserRepository userRepo; + private readonly IMapper mapper; + public UserService(IUserRepository userRepo, IMapper mapper) + { + this.userRepo = userRepo; + this.mapper = mapper; + } + + // Создание нового пользователя + public async Task CreateUserAsync( + string UserName, + string description, + Guid captainId, + DateTime BirthDate, + CancellationToken token + ) + { + // Создание пользователя + var user = new UserMainEntity + { + Id = Guid.NewGuid(), + UserName = UserName, + BirthDate = BirthDate + }; + await userRepo.AddAsync(user, token); + return user; + } + + // Удаление команды (только капитаном или администратором) + public async Task DeleteUserAsync( + Guid userId, + Guid requestingUserId, + CancellationToken token, + bool isAdmin = false + ) + { + throw new NotImplementedException(); + // await validation.CheckTeamExistsAsync(teamId, token); + // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + // await userRepo.RemoveAsync(teamId, token); + } + public async Task UpdateUserAsync( + Guid userId, + Guid requestingUserId, + CancellationToken token, + bool isAdmin = false + ) + { + throw new NotImplementedException(); + // await validation.CheckTeamExistsAsync(teamId, token); + // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); + // await userRepo.RemoveAsync(teamId, token); + } + + // Получение информации о команде по ID + public async Task GetUserByIdAsync(Guid userId, CancellationToken token) + { + // await validation.CheckTeamExistsAsync(teamId, token); + return await userRepo.GetByIdAsync(userId, token); + } + + // Получение списка команд + public async Task> GetUsersAllAsync(CancellationToken token) + { + + var teams = await userRepo.GetAllAsync(token); + return mapper.Map>(teams); + } + } +} From 9bde8f68ce7704f99c2b8c823f59a1c5d9b73dcb Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 01:58:59 +0300 Subject: [PATCH 07/56] Add mapper config --- MethodologyMain.API/Program.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index fe31320..8da3135 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -17,7 +17,6 @@ var builder = WebApplication.CreateBuilder(args); - builder.Services.AddControllers(); builder.Services.AddControllers() .AddJsonOptions(options => @@ -27,13 +26,14 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -var configuration = new MapperConfiguration(static cfg => +var mapperConfig = new MapperConfiguration(static cfg => { cfg.AddMaps(Assembly.GetExecutingAssembly()); cfg.AllowNullCollections = true; cfg.AddGlobalIgnore("Item"); } ); +IMapper mapper = mapperConfig.CreateMapper(); builder.Services.Configure(builder.Configuration.GetSection(nameof(RabbitMqOptions))); @@ -41,8 +41,11 @@ builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); builder.Services.AddScoped(); builder.Services.AddScoped(); + +builder.Services.AddSingleton(mapper); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + var connection = builder.Configuration.GetConnectionString("PostgresConnection"); builder.Services.AddDbContext(opt => opt.UseNpgsql(connection)); From b03a7cdff2628210ff20f8594c63b61e6398deb5 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 02:00:27 +0300 Subject: [PATCH 08/56] Update Properties --- MethodologyMain.API/Dockerfile | 16 ++++++---- MethodologyMain.API/Dockerfile.original | 30 +++++++++++++++++++ .../Properties/serviceDependencies.local.json | 20 ++++++++++++- 3 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 MethodologyMain.API/Dockerfile.original diff --git a/MethodologyMain.API/Dockerfile b/MethodologyMain.API/Dockerfile index 12a01a3..2d1f39f 100644 --- a/MethodologyMain.API/Dockerfile +++ b/MethodologyMain.API/Dockerfile @@ -12,19 +12,23 @@ EXPOSE 8081 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src -COPY ["MethodTeams1/MethodTeams1.csproj", "MethodTeams1/"] -RUN dotnet restore "./MethodTeams1/MethodTeams1.csproj" +COPY ["MethodologyMain.API/MethodologyMain.API.csproj", "MethodologyMain.API/"] +COPY ["MethodologyMain.Application/MethodologyMain.Application.csproj", "MethodologyMain.Application/"] +COPY ["MethodologyMain.Persistence/MethodologyMain.Persistence.csproj", "MethodologyMain.Persistence/"] +COPY ["MethodologyMain.Logic/MethodologyMain.Logic.csproj", "MethodologyMain.Logic/"] +COPY ["MethodologyMain.Infrastructure/MethodologyMain.Infrastructure.csproj", "MethodologyMain.Infrastructure/"] +RUN dotnet restore "./MethodologyMain.API/MethodologyMain.API.csproj" COPY . . -WORKDIR "/src/MethodTeams1" -RUN dotnet build "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/build +WORKDIR "/src/MethodologyMain.API" +RUN dotnet build "./MethodologyMain.API.csproj" -c $BUILD_CONFIGURATION -o /app/build # Этот этап используется для публикации проекта службы, который будет скопирован на последний этап FROM build AS publish ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +RUN dotnet publish "./MethodologyMain.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false # Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "MethodTeams1.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "MethodologyMain.API.dll"] \ No newline at end of file diff --git a/MethodologyMain.API/Dockerfile.original b/MethodologyMain.API/Dockerfile.original new file mode 100644 index 0000000..12a01a3 --- /dev/null +++ b/MethodologyMain.API/Dockerfile.original @@ -0,0 +1,30 @@ +# См. статью по ссылке https://aka.ms/customizecontainer, чтобы узнать как настроить контейнер отладки и как Visual Studio использует этот Dockerfile для создания образов для ускорения отладки. + +# Этот этап используется при запуске из VS в быстром режиме (по умолчанию для конфигурации отладки) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + + +# Этот этап используется для сборки проекта службы +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["MethodTeams1/MethodTeams1.csproj", "MethodTeams1/"] +RUN dotnet restore "./MethodTeams1/MethodTeams1.csproj" +COPY . . +WORKDIR "/src/MethodTeams1" +RUN dotnet build "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# Этот этап используется для публикации проекта службы, который будет скопирован на последний этап +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./MethodTeams1.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "MethodTeams1.dll"] \ No newline at end of file diff --git a/MethodologyMain.API/Properties/serviceDependencies.local.json b/MethodologyMain.API/Properties/serviceDependencies.local.json index 33703d5..6064c5b 100644 --- a/MethodologyMain.API/Properties/serviceDependencies.local.json +++ b/MethodologyMain.API/Properties/serviceDependencies.local.json @@ -1,3 +1,21 @@ { - "dependencies": {} + "dependencies": { + "rabbitmq1": { + "containerPorts": "5672:5672,15672:15672", + "secretStore": "LocalSecretsFile", + "containerName": "rabbitmq", + "containerImage": "rabbitmq:3-management-alpine", + "type": "rabbitmq.container", + "connectionId": "QueueConnection" + }, + "postgresql1": { + "containerPorts": "5432:5432", + "secretStore": "LocalSecretsFile", + "containerName": "postgresql", + "containerImage": "postgres", + "resourceId": null, + "type": "postgresql.container", + "connectionId": "ConnectionStrings:DatabaseConnection" + } + } } \ No newline at end of file From 35d89b61bdcd94d146b756165692b0b8310f24f3 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 02:00:57 +0300 Subject: [PATCH 09/56] Add for debug --- MethodologyMain.API/Controllers/TeamController.cs | 2 +- MethodologyMain.API/Middleware/ExceptionMiddleware.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 53e7548..18a1e90 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -309,7 +309,7 @@ public async Task>> GetTeamsAll(CancellationToken token) //} private Guid GetCurrentUserId() { - return Guid.Parse("1"); + return Guid.Parse("d5a492ca-9611-4fda-9ace-10ec38bb4d48"); } } } diff --git a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs index e17cdc9..9257a30 100644 --- a/MethodologyMain.API/Middleware/ExceptionMiddleware.cs +++ b/MethodologyMain.API/Middleware/ExceptionMiddleware.cs @@ -26,7 +26,7 @@ public async Task InvokeAsync(HttpContext context) _ = logQueueService.SendLogEventAsync(new AuthMetodology.Infrastructure.Models.RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Error, - Message = $"Exception was thrown.\nMessage: {ex.Message}\nSource: {ex.Source}", + Message = $"Exception was thrown.\nMessage: {ex.Message}, {ex.InnerException}\nSource: {ex.Source}", TimeStamp = DateTime.UtcNow }); HandleException(ex,context); From 840b49360d71214e3ee3ead6ec7272a21ccbf268 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 02:01:18 +0300 Subject: [PATCH 10/56] Add docker compose --- docker-compose.dcproj | 19 +++++++++ docker-compose.override.yml | 14 +++++++ docker-compose.yml | 82 +++++++++++++++++++++++++++++++++++++ launchSettings.json | 11 +++++ 4 files changed, 126 insertions(+) create mode 100644 docker-compose.dcproj create mode 100644 docker-compose.override.yml create mode 100644 docker-compose.yml create mode 100644 launchSettings.json diff --git a/docker-compose.dcproj b/docker-compose.dcproj new file mode 100644 index 0000000..87e67a7 --- /dev/null +++ b/docker-compose.dcproj @@ -0,0 +1,19 @@ + + + + 2.1 + Linux + False + 81dded9d-158b-e303-5f62-77a2896d2a5a + LaunchBrowser + {Scheme}://localhost:{ServicePort}/swagger + methodologymain.api + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..062650e --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,14 @@ +services: + methodologymain.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_HTTPS_PORTS=8081 + ports: + - "8080" + - "8081" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d292808 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,82 @@ +name: authMetodologyService + +services: + methodologymain.api: + image: ${DOCKER_REGISTRY-}methodologymainapi + build: + context: . + dockerfile: MethodologyMain.API/Dockerfile + + postgres: + container_name: auth_db + image: postgres:latest + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_DB: authdb + POSTGRES_USER: admin + POSTGRES_PASSWORD: password123! + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U admin -d authdb"] + interval: 10s + timeout: 3s + retries: 3 + networks: + - authNet + restart: unless-stopped + + pgadmin: + container_name: pgadmin + image: dpage/pgadmin4:latest + environment: + PGADMIN_DEFAULT_EMAIL: admin@example.com + PGADMIN_DEFAULT_PASSWORD: password + ports: + - "5050:80" + depends_on: + postgres: + condition: service_healthy + networks: + - authNet + restart: unless-stopped + + rabbitmq: + image: rabbitmq:management-alpine + container_name: rabbitmqForAuth + volumes: + - rabbit-data:/var/lib/rabbitmq + restart: always + ports: + - 5672:5672 + - 15672:15672 + networks: + - authNet + depends_on: + postgres: + condition: service_healthy + + redis: + image: redis + restart: always + volumes: + - redis-data:/data + ports: + - "6379:6379" + networks: + - authNet + depends_on: + postgres: + condition: service_healthy + +networks: + authNet: + name: authNet + driver: bridge + +volumes: + postgres-data: + rabbit-data: + redis-data: + grafana-data: \ No newline at end of file diff --git a/launchSettings.json b/launchSettings.json new file mode 100644 index 0000000..428a8d9 --- /dev/null +++ b/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "Docker Compose": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "serviceActions": { + "methodologymain.api": "StartDebugging" + } + } + } +} \ No newline at end of file From 7dce081de83feece333841705ff84ff6381b90f4 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 02:14:50 +0300 Subject: [PATCH 11/56] Fix log service in User Controller --- MethodologyMain.API/Controllers/UserController.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index 109aa8a..9afc49e 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -4,9 +4,9 @@ using Microsoft.AspNetCore.Mvc; using System.Security.Claims; using MethodologyMain.Application.Interface; -using AuthMetodology.Infrastructure.Interfaces; using AuthMetodology.Infrastructure.Models; using Serilog.Events; +using RabbitMqPublisher.Interface; namespace MethodologyMain.API.Controllers { @@ -15,16 +15,16 @@ namespace MethodologyMain.API.Controllers public class UserController : ControllerBase { private readonly ITeamService teamService; - private readonly ILogQueueService logQueueService; - public UserController(ITeamService teamService, ILogQueueService logQueueService) + private readonly IRabbitMqPublisherBase logPublishService; + public UserController(ITeamService teamService, IRabbitMqPublisherBase logPublishService) { this.teamService = teamService; - this.logQueueService = logQueueService; + this.logPublishService = logPublishService; } [HttpPost] public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { - _ = logQueueService.SendLogEventAsync(new RabbitMqLogPublish + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, From ae5a032cf83d3dbd2459840c24e0a3479d09ed97 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 19:44:41 +0300 Subject: [PATCH 12/56] Fix GenericRepository --- MethodologyMain.Persistence/Repository/GenericRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.Persistence/Repository/GenericRepository.cs b/MethodologyMain.Persistence/Repository/GenericRepository.cs index 43f0393..a6f2cd5 100644 --- a/MethodologyMain.Persistence/Repository/GenericRepository.cs +++ b/MethodologyMain.Persistence/Repository/GenericRepository.cs @@ -37,7 +37,7 @@ public async Task> GetAllAsync(CancellationToken token) public async Task GetByIdAsync(Guid id, CancellationToken token) { - return await _context.Set().FindAsync(id, token); + return await _context.Set().FindAsync([id], token); } public async Task RemoveAsync(T entity, CancellationToken token) From 8e03f38730b30a0001682102c47adfde6032c1f9 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 19:45:48 +0300 Subject: [PATCH 13/56] Add Update to Team Controller --- .../Controllers/TeamController.cs | 17 +++++++++ .../Interface/ITeamService.cs | 2 + .../Services/TeamService.cs | 3 +- .../Repository/TeamRepository.cs | 1 + .../Repository/UserRepository.cs | 37 ++++++++++++++++++- 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index c7bf9b8..6e15e0b 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -8,6 +8,7 @@ using Serilog.Events; using RabbitMqPublisher.Interface; using Newtonsoft.Json.Linq; +using MethodTeams.DTO; namespace MethodologyMain.API.Controllers { [ApiController] @@ -85,6 +86,22 @@ public async Task> GetTeam(Guid id, CancellationToken token) //} } + [HttpPut("{id}")] + //[Authorize] + public async Task UpdateTeam(Guid id, [FromBody] TeamInfoDto dto, CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "Update api/Team/id was called", + TimeStamp = DateTime.UtcNow + }, token); + Guid currentUserId = GetCurrentUserId(); + await teamService.UpdateTeamAsync(id, dto, currentUserId, token); + return NoContent(); + } + // Удаление команды [HttpDelete("{id}")] //[Authorize] diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index a0cb0f7..610091d 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,4 +1,5 @@ using MethodologyMain.Logic.Entities; +using MethodTeams.DTO; namespace MethodologyMain.Application.Interface { @@ -10,6 +11,7 @@ public interface ITeamService Task GetTeamByIdAsync(Guid teamId, CancellationToken token); Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); Task> GetTeamAllAsync(CancellationToken token); + Task UpdateTeamAsync(Guid teamId, TeamInfoDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 9d1dfff..c797a9f 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -72,7 +72,7 @@ public async Task DeleteTeamAsync( public async Task UpdateTeamAsync( Guid teamId, - Team team, + TeamInfoDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false @@ -81,6 +81,7 @@ public async Task UpdateTeamAsync( await validation.CheckTeamExistsAsync(teamId, token); await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); var teamEntity = await teamRepo.GetByIdAsync(teamId, token); + if (teamEntity.Id != team.Id) throw new InvalidOperationException(); teamEntity.Description = team.Description; teamEntity.Name = team.Name; teamEntity.HackathonId = team.HackathonId; diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index 1188b0a..c7bd220 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -16,6 +16,7 @@ public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, var user = await _context.Users .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == userId, token); + if (user == null) return true; return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; } public async Task CheckUserInTeamAsync(Guid userId, Guid teamId, CancellationToken token) diff --git a/MethodologyMain.Persistence/Repository/UserRepository.cs b/MethodologyMain.Persistence/Repository/UserRepository.cs index fa50e3e..25d507f 100644 --- a/MethodologyMain.Persistence/Repository/UserRepository.cs +++ b/MethodologyMain.Persistence/Repository/UserRepository.cs @@ -1,6 +1,9 @@ using MethodologyMain.Logic.Entities; using MethodologyMain.Logic.Models; +using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; +using MethodTeams.Models; +using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; @@ -9,12 +12,42 @@ namespace MethodologyMain.Persistence.Repository { - public class UserRepository: GenericRepository + public class UserRepository: GenericRepository, IUserRepository { public UserRepository(MyDbContext context) : base(context) { } - + public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token) + { + CheckCancellation(token); + token.ThrowIfCancellationRequested(); + var user = await _context.Users + .AsNoTracking() + .FirstOrDefaultAsync(e => e.Id == userId, token); + return user.Teams.Find(m => m.Team.HackathonId == hackathonId) != null; + } + public async Task RemoveAsync(Guid userId, CancellationToken token) + { + CheckCancellation(token); + var user = await _context.Users.FindAsync([userId], token); + _context.Users.Remove(user); + await SaveChangesAsync(token); + } + public async Task UpdateAsync(Guid userId, UserMain user, CancellationToken token) + { + CheckCancellation(token); + _context.Entry(user).State = EntityState.Modified; + await SaveChangesAsync(token); + } + private static void CheckCancellation(CancellationToken token) + { + token.ThrowIfCancellationRequested(); + } + private async Task SaveChangesAsync(CancellationToken token) + { + CheckCancellation(token); + await _context.SaveChangesAsync(token); + } } } From 1678df64c5146f0b4270f373c6a8161cc274f6e7 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Thu, 24 Apr 2025 19:46:29 +0300 Subject: [PATCH 14/56] Fix Program --- MethodologyMain.API/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 1ae8352..4381df7 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -21,7 +21,7 @@ var builder = WebApplication.CreateBuilder(args); -builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); +//builder.Services.AddApiAuthentication(builder.Services.BuildServiceProvider().GetRequiredService>()); builder.Services.AddControllers(); builder.Services.AddControllers() From 04bc5f99a7e6e9282a8088d86c92d9a464e7e5bb Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sat, 26 Apr 2025 17:49:34 +0300 Subject: [PATCH 15/56] Update Team to return dto --- .../Controllers/TeamController.cs | 56 +++++++------------ MethodologyMain.API/Program.cs | 2 +- .../DTO/TeamInfoDto.cs | 4 +- .../DTO/UpdateTeamDto.cs | 10 ++++ .../Interface/ITeamService.cs | 12 ++-- .../Profiles/TeamProfile.cs | 6 ++ .../Services/TeamService.cs | 37 ++++++------ .../Interfaces/ITeamRepository.cs | 3 + .../Repository/TeamRepository.cs | 8 ++- 9 files changed, 75 insertions(+), 63 deletions(-) create mode 100644 MethodologyMain.Application/DTO/UpdateTeamDto.cs diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 6e15e0b..eec4802 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -8,7 +8,6 @@ using Serilog.Events; using RabbitMqPublisher.Interface; using Newtonsoft.Json.Linq; -using MethodTeams.DTO; namespace MethodologyMain.API.Controllers { [ApiController] @@ -38,10 +37,25 @@ public async Task GetDummyData(CancellationToken cancellationToke return Ok(data); } + // Получение списка команд + [HttpGet] + public async Task>> GetTeamsAll(CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/Team was called", + TimeStamp = DateTime.UtcNow + }, token); + var teams = await teamService.GetTeamAllAsync(token); + return Ok(teams); + } + // Создание команды [HttpPost] //[Authorize] - public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -65,7 +79,7 @@ public async Task> CreateTeam([FromBody] CreateTeamDto dto, C // Получение информации о команде [HttpGet("{id}")] - public async Task> GetTeam(Guid id, CancellationToken token) + public async Task> GetTeam(Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -86,9 +100,9 @@ public async Task> GetTeam(Guid id, CancellationToken token) //} } - [HttpPut("{id}")] + [HttpPut] //[Authorize] - public async Task UpdateTeam(Guid id, [FromBody] TeamInfoDto dto, CancellationToken token) + public async Task UpdateTeam([FromBody] UpdateTeamDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -98,7 +112,7 @@ public async Task UpdateTeam(Guid id, [FromBody] TeamInfoDto dto, TimeStamp = DateTime.UtcNow }, token); Guid currentUserId = GetCurrentUserId(); - await teamService.UpdateTeamAsync(id, dto, currentUserId, token); + await teamService.UpdateTeamAsync(dto, currentUserId, token); return NoContent(); } @@ -255,36 +269,6 @@ public async Task TransferCaptainRights(Guid id, [FromBody] AddUse //} } - // Получение списка команд - [HttpGet] - public async Task>> GetTeamsAll(CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team was called", - TimeStamp = DateTime.UtcNow - }, token); - var teams = await teamService.GetTeamAllAsync(token); - return Ok(teams); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} - } //// Получение списка команд для события //[HttpGet("event/{eventId}")] diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 4381df7..e491a75 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -8,7 +8,6 @@ using MethodologyMain.Infrastructure.Services; using MethodologyMain.Persistence.Interfaces; using MethodologyMain.Persistence.Repository; -using MethodTeams.DTO; using System.Reflection; using MethodologyMain.Application.Profiles; using Microsoft.EntityFrameworkCore; @@ -18,6 +17,7 @@ using MethodologyMain.Infrastructure.Models; using MethodologyMain.API.Extensions; using Microsoft.Extensions.Options; +using MethodologyMain.Application.DTO; var builder = WebApplication.CreateBuilder(args); diff --git a/MethodologyMain.Application/DTO/TeamInfoDto.cs b/MethodologyMain.Application/DTO/TeamInfoDto.cs index 182b720..68d702a 100644 --- a/MethodologyMain.Application/DTO/TeamInfoDto.cs +++ b/MethodologyMain.Application/DTO/TeamInfoDto.cs @@ -1,11 +1,11 @@ -namespace MethodTeams.DTO +namespace MethodologyMain.Application.DTO { // DTO для информации о команде public class TeamInfoDto { public Guid Id { get; set; } - public string Name { get; set; } + public required string Name { get; set; } public string? Description { get; set; } public Guid CaptainId { get; set; } public Guid HackathonId { get; set; } diff --git a/MethodologyMain.Application/DTO/UpdateTeamDto.cs b/MethodologyMain.Application/DTO/UpdateTeamDto.cs new file mode 100644 index 0000000..8d30d8f --- /dev/null +++ b/MethodologyMain.Application/DTO/UpdateTeamDto.cs @@ -0,0 +1,10 @@ +namespace MethodologyMain.Application.DTO +{ + public class UpdateTeamDto + { + public Guid Id { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } + public Guid? HackathonId { get; set; } + } +} diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index 610091d..da11b0b 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,17 +1,17 @@ -using MethodologyMain.Logic.Entities; -using MethodTeams.DTO; +using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; namespace MethodologyMain.Application.Interface { public interface ITeamService { Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); - Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId, CancellationToken token); + Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId, CancellationToken token); Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); - Task GetTeamByIdAsync(Guid teamId, CancellationToken token); + Task GetTeamByIdAsync(Guid teamId, CancellationToken token); Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); - Task> GetTeamAllAsync(CancellationToken token); - Task UpdateTeamAsync(Guid teamId, TeamInfoDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); + Task> GetTeamAllAsync(CancellationToken token); + Task UpdateTeamAsync(UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); diff --git a/MethodologyMain.Application/Profiles/TeamProfile.cs b/MethodologyMain.Application/Profiles/TeamProfile.cs index 087fae9..ef6d157 100644 --- a/MethodologyMain.Application/Profiles/TeamProfile.cs +++ b/MethodologyMain.Application/Profiles/TeamProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; using MethodTeams.Models; using System; @@ -16,6 +17,11 @@ public TeamProfile() CreateMap(); CreateMap(); + + CreateProjection() + .ForMember(dto => dto.MemberCount, conf => conf.MapFrom(t => t.Members.Count)); + CreateMap() + .ForMember(dto => dto.MemberCount, conf => conf.MapFrom(t => t.Members.Count)); } } } diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index c797a9f..91b68f5 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -5,7 +5,7 @@ using MethodTeams.Models; using AutoMapper; using MethodologyMain.Logic.Models; -using MethodTeams.DTO; +using MethodologyMain.Application.DTO; namespace MethodTeams.Services { @@ -25,7 +25,7 @@ public TeamService( } // Создание новой команды - public async Task CreateTeamAsync( + public async Task CreateTeamAsync( string name, string description, Guid captainId, @@ -54,7 +54,7 @@ CancellationToken token }; team.Members.Add(member); await teamRepo.AddAsync(team, token); - return team; + return mapper.Map(team); } // Удаление команды (только капитаном или администратором) @@ -71,21 +71,23 @@ public async Task DeleteTeamAsync( } public async Task UpdateTeamAsync( - Guid teamId, - TeamInfoDto team, + UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false ) { - await validation.CheckTeamExistsAsync(teamId, token); - await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); - var teamEntity = await teamRepo.GetByIdAsync(teamId, token); - if (teamEntity.Id != team.Id) throw new InvalidOperationException(); - teamEntity.Description = team.Description; - teamEntity.Name = team.Name; - teamEntity.HackathonId = team.HackathonId; + await validation.CheckTeamExistsAsync(team.Id, token); + await validation.CheckUserIsCaptainOrAdminAsync(team.Id, requestingUserId, isAdmin, token); + var teamEntity = await teamRepo.GetByIdAsync(team.Id, token); + if (string.IsNullOrEmpty(team.Description) && teamEntity.Description != team.Description) + teamEntity.Description = team.Description; + if (string.IsNullOrEmpty(team.Name) && teamEntity.Name != team.Name) + teamEntity.Name = team.Name; + if (team.HackathonId != null && teamEntity.HackathonId != team.HackathonId) + teamEntity.HackathonId = (Guid)team.HackathonId; await teamRepo.UpdateTeamAsync(teamEntity, token); + } // Добавление пользователя в команду @@ -134,10 +136,11 @@ CancellationToken token await teamRepo.TransferCaptainAsync(newCaptainId, teamId, token); } // Получение информации о команде по ID - public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) + public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) { await validation.CheckTeamExistsAsync(teamId, token); - return await teamRepo.GetByIdAsync(teamId, token); + var team = await teamRepo.GetTeamAsync(teamId, token); + return mapper.Map(team); } // Получение списка участников команды public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) @@ -147,12 +150,12 @@ public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken } // Получение списка команд - public async Task> GetTeamAllAsync(CancellationToken token) + public async Task> GetTeamAllAsync(CancellationToken token) { - var teams = await teamRepo.GetAllAsync(token); + var teams = await teamRepo.GetTeamsAllAsync(token); //return mapper.Map>(teams); - return teams.ToList(); + return mapper.ProjectTo(teams.AsQueryable()).ToList(); } //// Проверка, является ли пользователь капитаном команды diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index 329d4e3..9700f21 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -1,4 +1,5 @@ using MethodologyMain.Logic.Entities; +using System.Threading.Tasks; namespace MethodologyMain.Persistence.Interfaces { @@ -12,6 +13,8 @@ public interface ITeamRepository : IGenericRepository Task GetHackathonIdAsync(Guid teamId, CancellationToken token); Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); Task UpdateTeamAsync(TeamEntity team, CancellationToken token); + Task> GetTeamsAllAsync(CancellationToken token); + Task GetTeamAsync(Guid teamId, CancellationToken token); Task RemoveMemberAsync(Guid userId, Guid teamId, CancellationToken token); Task RemoveTeamAsync(Guid teamId, CancellationToken token); Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, CancellationToken token); diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index c7bd220..a31dd6b 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -1,6 +1,7 @@ using MethodologyMain.Logic.Entities; using MethodologyMain.Persistence.Interfaces; using MethodTeams.Data; +using MethodTeams.Models; using Microsoft.EntityFrameworkCore; namespace MethodologyMain.Persistence.Repository @@ -83,6 +84,11 @@ public async Task UpdateTeamAsync(TeamEntity team, CancellationToken token) _context.Update(team); await _context.SaveChangesAsync(token); } + public async Task> GetTeamsAllAsync(CancellationToken token) + { + CheckCancellation(token); + return await _context.Teams.Include(m => m.Members).ToListAsync(token); + } private static void CheckCancellation(CancellationToken token) { token.ThrowIfCancellationRequested(); @@ -94,7 +100,7 @@ private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationT .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == teamId, token); } - private async Task GetTeamAsync(Guid teamId, CancellationToken token) + public async Task GetTeamAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); return await _context.Teams.Include(m => m.Members).FirstOrDefaultAsync(m => m.Id == teamId); From 4d6ef4af63a5275ee6dd9a2c7d46bdac6ca37fae Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sat, 26 Apr 2025 17:50:14 +0300 Subject: [PATCH 16/56] Update UserMainEntity --- MethodologyMain.Logic/Entities/UserMainEntity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index 10d3b2e..eb4a271 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -18,7 +18,7 @@ public class UserMainEntity [Column("lastName")] public string LastName { get; set; } = string.Empty; [Column("middleName")] - public string Surname { get; set; } = string.Empty; + public string MiddleName { get; set; } = string.Empty; [Column("userName")] public string UserName { get; set; } = string.Empty; [Column("Telegram")] From a6c37c6775026f4ba0a290975645451826f3daaa Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sat, 26 Apr 2025 17:50:55 +0300 Subject: [PATCH 17/56] Fix UserRepository and add UserInfoDto --- MethodologyMain.Application/DTO/UserInfoDto.cs | 17 +++++++++++++++++ .../Repository/UserRepository.cs | 5 ++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 MethodologyMain.Application/DTO/UserInfoDto.cs diff --git a/MethodologyMain.Application/DTO/UserInfoDto.cs b/MethodologyMain.Application/DTO/UserInfoDto.cs new file mode 100644 index 0000000..a76e30a --- /dev/null +++ b/MethodologyMain.Application/DTO/UserInfoDto.cs @@ -0,0 +1,17 @@ +using MethodologyMain.Logic.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Application.DTO +{ + public class UserInfoDto + { + public Guid Id { get; set; } + public required string UserName { get; set; } + public string? Education { get; set; } + public List? Tags { get; set; } + } +} diff --git a/MethodologyMain.Persistence/Repository/UserRepository.cs b/MethodologyMain.Persistence/Repository/UserRepository.cs index 25d507f..9f93f4e 100644 --- a/MethodologyMain.Persistence/Repository/UserRepository.cs +++ b/MethodologyMain.Persistence/Repository/UserRepository.cs @@ -20,7 +20,6 @@ public UserRepository(MyDbContext context) : base(context) public async Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token) { CheckCancellation(token); - token.ThrowIfCancellationRequested(); var user = await _context.Users .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == userId, token); @@ -33,10 +32,10 @@ public async Task RemoveAsync(Guid userId, CancellationToken token) _context.Users.Remove(user); await SaveChangesAsync(token); } - public async Task UpdateAsync(Guid userId, UserMain user, CancellationToken token) + public async Task UpdateAsync(UserMainEntity user, CancellationToken token) { CheckCancellation(token); - _context.Entry(user).State = EntityState.Modified; + _context.Update(user); await SaveChangesAsync(token); } private static void CheckCancellation(CancellationToken token) From d58a362384ca7b233f9fdf1a1a6981f820034410 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sat, 26 Apr 2025 19:25:13 +0300 Subject: [PATCH 18/56] Change Logic --- .../Entities/HackathonEntity.cs | 33 +++++++++++------ .../Entities/OrganizationEntity.cs | 13 ++----- MethodologyMain.Logic/Entities/TagEntity.cs | 2 + MethodologyMain.Logic/Entities/TeamEntity.cs | 5 ++- .../Entities/TeamTagEntity.cs | 23 ++++++++++++ .../Entities/UserMainEntity.cs | 27 +++++++++++++- MethodologyMain.Logic/Models/Hackathon.cs | 37 ++++++++----------- MethodologyMain.Logic/Models/Organization.cs | 4 +- MethodologyMain.Logic/Models/Prize.cs | 8 ++++ MethodologyMain.Logic/Models/ScheduleItem.cs | 16 ++++++++ MethodologyMain.Logic/Models/Team.cs | 10 ++--- MethodologyMain.Logic/Models/TeamSize.cs | 14 +++++++ MethodologyMain.Logic/Models/UserMain.cs | 7 ++++ 13 files changed, 146 insertions(+), 53 deletions(-) create mode 100644 MethodologyMain.Logic/Entities/TeamTagEntity.cs create mode 100644 MethodologyMain.Logic/Models/Prize.cs create mode 100644 MethodologyMain.Logic/Models/ScheduleItem.cs create mode 100644 MethodologyMain.Logic/Models/TeamSize.cs diff --git a/MethodologyMain.Logic/Entities/HackathonEntity.cs b/MethodologyMain.Logic/Entities/HackathonEntity.cs index 1baa552..b163588 100644 --- a/MethodologyMain.Logic/Entities/HackathonEntity.cs +++ b/MethodologyMain.Logic/Entities/HackathonEntity.cs @@ -1,4 +1,5 @@ -using System; +using MethodologyMain.Logic.Models; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -21,8 +22,20 @@ public class HackathonEntity [Column("name")] public required string Name { get; set; } - [Column("prize")] - public required decimal Prize { get; set; } + [Column("description")] + public string Description { get; set; } = string.Empty; + + [Column("startDate")] + public required DateOnly StartDate { get; set; } + + [Column("endDate")] + public required DateOnly EndDate { get; set; } + + [Column("location")] + public string Location { get; set; } = string.Empty; + + [Column("imageUrl")] + public string ImageUrl { get; set; } = string.Empty; [Column("minTeamSize")] public required int MinTeamSize { get; set; } @@ -30,21 +43,19 @@ public class HackathonEntity [Column("maxTeamSize")] public required int MaxTeamSize { get; set; } - [Column("startDate")] - public required DateTime StartDate { get; set; } + [Column("website")] + public string Website { get; set; } = string.Empty; - [Column("endDate")] - public required DateTime EndDate { get; set; } + [Column("prize")] + public required List Prizes { get; set; } - [Column("additionalInfo")] - public string AdditionalInfo { get; set; } = string.Empty; + [Column("schedule")] + public required List Schedule { get; set; } public OrganizationEntity Organization { get; set; } = null!; public List Teams { get; set; } = new List(); public List Tags { get; set; } = new List(); - - public List Tracks { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Entities/OrganizationEntity.cs b/MethodologyMain.Logic/Entities/OrganizationEntity.cs index 5655bee..ff8fb61 100644 --- a/MethodologyMain.Logic/Entities/OrganizationEntity.cs +++ b/MethodologyMain.Logic/Entities/OrganizationEntity.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MethodologyMain.Logic.Entities { @@ -19,10 +14,10 @@ public class OrganizationEntity public required string Name { get; set; } [Column("description")] - public required string Description { get; set; } + public string Description { get; set; } = string.Empty; - [Column("linkToWebsite")] - public required string LinkToWebSite { get; set; } = string.Empty; + [Column("logo")] + public string Logo { get; set; } = string.Empty; public List Hackathons { get; set; } = new List(); } diff --git a/MethodologyMain.Logic/Entities/TagEntity.cs b/MethodologyMain.Logic/Entities/TagEntity.cs index 6a22c84..a70cb32 100644 --- a/MethodologyMain.Logic/Entities/TagEntity.cs +++ b/MethodologyMain.Logic/Entities/TagEntity.cs @@ -24,5 +24,7 @@ public class TagEntity public List Users { get; set; } = new List(); public List Hacksthons { get; set; } = new List(); + + public List Teams { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Entities/TeamEntity.cs b/MethodologyMain.Logic/Entities/TeamEntity.cs index 8ef81ba..4b95e09 100644 --- a/MethodologyMain.Logic/Entities/TeamEntity.cs +++ b/MethodologyMain.Logic/Entities/TeamEntity.cs @@ -14,7 +14,7 @@ public class TeamEntity public required Guid HackathonId { get; set; } [Column("name")] - public required string Name { get; set; } = string.Empty; + public required string Name { get; set; } [Column("description")] public string Description { get; set; } = string.Empty; @@ -23,9 +23,10 @@ public class TeamEntity public required Guid CaptainId { get; set; } [Column("teamCreatedAt")] - public DateTime TeamCreatedAt { get; set; } + public DateTime TeamCreatedAt { get; set; } = DateTime.UtcNow; // Навигационное свойство для связи с участниками + public List Tags { get; set; } = new List(); public List Members { get; set; } = new List(); public HackathonEntity Hackathon { get; set; } = null!; } diff --git a/MethodologyMain.Logic/Entities/TeamTagEntity.cs b/MethodologyMain.Logic/Entities/TeamTagEntity.cs new file mode 100644 index 0000000..76211ac --- /dev/null +++ b/MethodologyMain.Logic/Entities/TeamTagEntity.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Entities +{ + [Table("teamTag", Schema = "mainSchema")] + public class TeamTagEntity + { + [Column("teamId")] + public Guid TeamId { get; set; } + + [Column("tagId")] + public Guid TagId { get; set; } + + public TeamEntity Team { get; set; } = null!; + + public TagEntity Tag { get; set; } = null!; + } +} diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index eb4a271..155cfff 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -9,21 +9,46 @@ public class UserMainEntity [Key] [Column("id")] public required Guid Id { get; set; } + [Column("birthDate")] public DateTime BirthDate { get; set; } = DateTime.MinValue; + [Column("education")] public string Education { get; set; } = string.Empty; + [Column("firstName")] public string FirstName { get; set; } = string.Empty; + [Column("lastName")] public string LastName { get; set; } = string.Empty; + [Column("middleName")] public string MiddleName { get; set; } = string.Empty; + [Column("userName")] public string UserName { get; set; } = string.Empty; - [Column("Telegram")] + + [Column("photoUrl")] + public string PhotoUrl { get; set; } = string.Empty; + + [Column("createdAt")] + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + [Column("location")] + public string Location { get; set; } = string.Empty; + + [Column("telegram")] public string Telegram { get; set; } = string.Empty; + [Column("github")] + public string Github { get; set; } = string.Empty; + + [Column("website")] + public string Website { get; set; } = string.Empty; + + [Column("skills")] + public string Skills { get; set; } = string.Empty; + public List Teams { get; set; } = new List(); diff --git a/MethodologyMain.Logic/Models/Hackathon.cs b/MethodologyMain.Logic/Models/Hackathon.cs index 7a367f6..22ffd3f 100644 --- a/MethodologyMain.Logic/Models/Hackathon.cs +++ b/MethodologyMain.Logic/Models/Hackathon.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,30 +11,22 @@ namespace MethodologyMain.Logic.Models { public class Hackathon { - public required Guid Id { get; set; } - - public required Guid OrganizationId { get; set; } - + public Guid Id { get; set; } public required string Name { get; set; } - - public required decimal Prize { get; set; } - - public required int MinTeamSize { get; set; } - - public required int MaxTeamSize { get; set; } - - public required DateTime StartDate { get; set; } - - public required DateTime EndDate { get; set; } - - public string AdditionalInfo { get; set; } = string.Empty; - + public string Description { get; set; } = string.Empty; + public required Guid OrganizationId { get; set; } + public required DateOnly StartDate { get; set; } + public required DateOnly EndDate { get; set; } + public string Location { get; set; } = string.Empty; + public string ImageUrl { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public TeamSize TeamSize { get; set; } = null!; + public int MinMembers { get; set; } = 2; + public int MaxMembers { get; set; } = 8; + public List Prizes { get; set; } = null!; + public List Schedule { get; set; } = null!; public OrganizationEntity Organization { get; set; } = null!; - - public List Teams { get; set; } = new List(); - public List Tags { get; set; } = new List(); - - public List Tracks { get; set; } = new List(); + public List Teams { get; set; } = new List(); } } diff --git a/MethodologyMain.Logic/Models/Organization.cs b/MethodologyMain.Logic/Models/Organization.cs index 3c06cf0..3299fd6 100644 --- a/MethodologyMain.Logic/Models/Organization.cs +++ b/MethodologyMain.Logic/Models/Organization.cs @@ -14,9 +14,9 @@ public class Organization public required string Name { get; set; } - public required string Description { get; set; } + public string Description { get; set; } = string.Empty; - public required string LinkToWebSite { get; set; } = string.Empty; + public string Logo { get; set; } = string.Empty; public List Hackathons { get; set; } = new List(); } diff --git a/MethodologyMain.Logic/Models/Prize.cs b/MethodologyMain.Logic/Models/Prize.cs new file mode 100644 index 0000000..4fd07dd --- /dev/null +++ b/MethodologyMain.Logic/Models/Prize.cs @@ -0,0 +1,8 @@ +namespace MethodologyMain.Logic.Models +{ + public class Prize + { + public required string Place { get; set; } + public required string Description { get; set; } + } +} diff --git a/MethodologyMain.Logic/Models/ScheduleItem.cs b/MethodologyMain.Logic/Models/ScheduleItem.cs new file mode 100644 index 0000000..2eb4d28 --- /dev/null +++ b/MethodologyMain.Logic/Models/ScheduleItem.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Models +{ + public class ScheduleItem + { + public required DateOnly Date { get; set; } + public required TimeOnly Time { get; set; } + public required string Title { get; set; } + public string Description { get; set; } = string.Empty; + } +} diff --git a/MethodologyMain.Logic/Models/Team.cs b/MethodologyMain.Logic/Models/Team.cs index a10f2d3..2d05dfc 100644 --- a/MethodologyMain.Logic/Models/Team.cs +++ b/MethodologyMain.Logic/Models/Team.cs @@ -6,17 +6,15 @@ namespace MethodTeams.Models public class Team { public required Guid Id { get; set; } - public required Guid HackathonId { get; set; } - - public required string Name { get; set; } = string.Empty; - + public required string Name { get; set; } public string Description { get; set; } = string.Empty; + public required int MaxMembers { get; set; } public required Guid CaptainId { get; set; } - - public DateTime CreatedAt { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Навигационное свойство для связи с участниками + public List Tags { get; set; } = new List(); public List Members { get; set; } = new List(); public HackathonEntity Hackathon { get; set; } = null!; } diff --git a/MethodologyMain.Logic/Models/TeamSize.cs b/MethodologyMain.Logic/Models/TeamSize.cs new file mode 100644 index 0000000..6afa829 --- /dev/null +++ b/MethodologyMain.Logic/Models/TeamSize.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MethodologyMain.Logic.Models +{ + public class TeamSize + { + public int Min { get; set; } + public int Max { get; set; } + } +} diff --git a/MethodologyMain.Logic/Models/UserMain.cs b/MethodologyMain.Logic/Models/UserMain.cs index 3ba043f..a42ac9d 100644 --- a/MethodologyMain.Logic/Models/UserMain.cs +++ b/MethodologyMain.Logic/Models/UserMain.cs @@ -19,6 +19,13 @@ public class UserMain public string LastName { get; set; } = string.Empty; public string MiddleName { get; set; } = string.Empty; public string UserName { get; set; } = string.Empty; + public string PhotoUrl { get; set; } = string.Empty; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public string Location { get; set; } = string.Empty; + public string Telegram { get; set; } = string.Empty; + public string Github { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public string Skills { get; set; } = string.Empty; public List Teams { get; set; } = new List(); From d346949a1541d310055443b9bb44f56f49167886 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sat, 26 Apr 2025 19:25:19 +0300 Subject: [PATCH 19/56] Add DTO --- .../DTO/GetHackathonDto.cs | 23 +++++++++++++++++++ MethodologyMain.Application/DTO/GetTeamDto.cs | 17 ++++++++++++++ MethodologyMain.Application/DTO/GetUserDto.cs | 19 +++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 MethodologyMain.Application/DTO/GetHackathonDto.cs create mode 100644 MethodologyMain.Application/DTO/GetTeamDto.cs create mode 100644 MethodologyMain.Application/DTO/GetUserDto.cs diff --git a/MethodologyMain.Application/DTO/GetHackathonDto.cs b/MethodologyMain.Application/DTO/GetHackathonDto.cs new file mode 100644 index 0000000..d1cba9e --- /dev/null +++ b/MethodologyMain.Application/DTO/GetHackathonDto.cs @@ -0,0 +1,23 @@ +using MethodologyMain.Logic.Models; + +namespace MethodologyMain.Application.DTO +{ + public class GetHackathonDto + { + public Guid Id { get; set; } + public required string Name { get; set; } + public string Description { get; set; } = string.Empty; + public required DateOnly StartDate { get; set; } + public required DateOnly EndDate { get; set; } + public string Location { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public string ImageUrl { get; set; } = string.Empty; + public string OrganizerName { get; set; } = string.Empty; + public string OrganizerLogo { get; set; } = string.Empty; + public TeamSize TeamSize { get; set; } = null!; + public string Website { get; set; } = string.Empty; + public List Prizes { get; set; } = null!; + public List Schedule { get; set; } = null!; + + } +} diff --git a/MethodologyMain.Application/DTO/GetTeamDto.cs b/MethodologyMain.Application/DTO/GetTeamDto.cs new file mode 100644 index 0000000..19da396 --- /dev/null +++ b/MethodologyMain.Application/DTO/GetTeamDto.cs @@ -0,0 +1,17 @@ +using MethodologyMain.Logic.Entities; + +namespace MethodologyMain.Application.DTO +{ + class GetTeamDto + { + public Guid Id { get; set; } + public Guid HackathonId { get; set; } + public required string Name { get; set; } + public string Description { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public List Members { get; set; } = null!; + public int MaxMembers { get; set; } + public Guid CreatedBy { get; set; } + public DateTime CreatedAt { get; set; } + } +} diff --git a/MethodologyMain.Application/DTO/GetUserDto.cs b/MethodologyMain.Application/DTO/GetUserDto.cs new file mode 100644 index 0000000..667504d --- /dev/null +++ b/MethodologyMain.Application/DTO/GetUserDto.cs @@ -0,0 +1,19 @@ + + +namespace MethodologyMain.Application.DTO +{ + public class GetUserDto + { + public Guid Id { get; set; } + public required string Name { get; set; } + public string Email { get; set; } = string.Empty; + public string Bio { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public string PhotoUrl { get; set; } = string.Empty; + public DateTime CreatedAt { get; set; } + public string Location { get; set; } = string.Empty; + public string Github { get; set; } = string.Empty; + public string Website { get; set; } = string.Empty; + public List Skills { get; set; } = null!; + } +} From e8c4a556365e2f92c35299076cccc8de493f6352 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 14:20:31 +0300 Subject: [PATCH 20/56] Add cancelationtoken for HackathonRepository --- .../Interfaces/IHackathonRepository.cs | 12 +++--- .../Repository/HackathonRepository.cs | 37 ++++++++++++++----- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs b/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs index 2fdc564..0afcbcf 100644 --- a/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IHackathonRepository.cs @@ -5,12 +5,10 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IHackathonRepository { - Task GetByIdAsync(Guid id); - - Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10); - - Task> GetAllHackathonsAsync(int page = 1, int pageSize = 10); - - Task> GetHackathonsByFlexibleSearchAsync(int page, int pageSize, Expression> filter = null); + Task GetByIdAsync(Guid id, CancellationToken token = default); + Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10, CancellationToken token = default); + Task> GetAllHackathonsAsync(CancellationToken token = default); + Task> GetAllHackathonsPagedAsync(int page = 1, int pageSize = 10, CancellationToken token = default); + Task> GetHackathonsByFlexibleSearchAsync(int page, int pageSize, Expression> filter = null, CancellationToken token = default); } } diff --git a/MethodologyMain.Persistence/Repository/HackathonRepository.cs b/MethodologyMain.Persistence/Repository/HackathonRepository.cs index e1155b8..f1cfd7a 100644 --- a/MethodologyMain.Persistence/Repository/HackathonRepository.cs +++ b/MethodologyMain.Persistence/Repository/HackathonRepository.cs @@ -3,6 +3,7 @@ using MethodTeams.Data; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; +using System.Threading; namespace MethodologyMain.Persistence.Repository { @@ -13,30 +14,46 @@ public HackathonRepository(MyDbContext context) { this.context = context; } - public async Task> GetAllCurrentHackathonsAsync(int page = 1, int pageSize = 10) + public async Task> GetAllCurrentHackathonsAsync( + int page = 1, + int pageSize = 10, + CancellationToken token = default + ) { return await context.Hackathons .AsNoTracking() - .Where(h => h.EndDate > DateTime.UtcNow) + .Where(h => h.EndDate > DateOnly.FromDateTime(DateTime.Now)) .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } - public async Task GetByIdAsync(Guid id) + public async Task GetByIdAsync(Guid id, CancellationToken token = default) { - return await context.Hackathons.FindAsync(id); + return await context.Hackathons.FindAsync([id], token); } - - public async Task> GetAllHackathonsAsync(int page = 1, int pageSize = 10) + public async Task> GetAllHackathonsAsync(CancellationToken token = default) + { + return await context.Hackathons.AsNoTracking().ToListAsync(token); + } + public async Task> GetAllHackathonsPagedAsync( + int page = 1, + int pageSize = 10, + CancellationToken token = default + ) { return await context.Hackathons.AsNoTracking() .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } - public async Task> GetHackathonsByFlexibleSearchAsync(int page,int pageSize, Expression> filter = null) + public async Task> GetHackathonsByFlexibleSearchAsync( + int page, + int pageSize, + Expression> filter = null, + CancellationToken token = default + ) { var query = context.Hackathons.AsQueryable(); @@ -47,7 +64,7 @@ public async Task> GetHackathonsByFlexibleSearchAsync(int return await query .Skip((page - 1) * pageSize) .Take(pageSize) - .ToListAsync(); + .ToListAsync(token); } } } From 20852a59443d80c78c76baf676810dc054a4a3e1 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 14:21:17 +0300 Subject: [PATCH 21/56] Fix Entities --- .../Entities/HackathonEntity.cs | 4 +-- .../Entities/HackathonTagEntity.cs | 2 +- .../Data/MyDbContext.cs | 26 ++++++++++++------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/MethodologyMain.Logic/Entities/HackathonEntity.cs b/MethodologyMain.Logic/Entities/HackathonEntity.cs index b163588..3b8f979 100644 --- a/MethodologyMain.Logic/Entities/HackathonEntity.cs +++ b/MethodologyMain.Logic/Entities/HackathonEntity.cs @@ -47,10 +47,10 @@ public class HackathonEntity public string Website { get; set; } = string.Empty; [Column("prize")] - public required List Prizes { get; set; } + public required string Prizes { get; set; } [Column("schedule")] - public required List Schedule { get; set; } + public required string Schedule { get; set; } public OrganizationEntity Organization { get; set; } = null!; diff --git a/MethodologyMain.Logic/Entities/HackathonTagEntity.cs b/MethodologyMain.Logic/Entities/HackathonTagEntity.cs index 479a012..bad04c5 100644 --- a/MethodologyMain.Logic/Entities/HackathonTagEntity.cs +++ b/MethodologyMain.Logic/Entities/HackathonTagEntity.cs @@ -8,7 +8,7 @@ namespace MethodologyMain.Logic.Entities { - [Table("hackthonTag")] + [Table("hackathonTag", Schema = "mainSchema")] public class HackathonTagEntity { [Column("hackathonId")] diff --git a/MethodologyMain.Persistence/Data/MyDbContext.cs b/MethodologyMain.Persistence/Data/MyDbContext.cs index d50ca31..6da0ced 100644 --- a/MethodologyMain.Persistence/Data/MyDbContext.cs +++ b/MethodologyMain.Persistence/Data/MyDbContext.cs @@ -1,4 +1,5 @@ using MethodologyMain.Logic.Entities; +using MethodologyMain.Logic.Models; using Microsoft.EntityFrameworkCore; namespace MethodTeams.Data @@ -8,11 +9,8 @@ public class MyDbContext : DbContext public MyDbContext(DbContextOptions options) : base(options) { } public DbSet Teams { get; set; } public DbSet Users { get; set; } - public DbSet Organizations { get; set; } - public DbSet Hackathons { get; set; } - public DbSet Tags { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -22,6 +20,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity() .HasKey(e => new {e.TagId, e.UserId}); + modelBuilder.Entity() + .HasKey(e => new { e.TagId, e.TeamId }); + modelBuilder.Entity() .HasKey(e => new {e.UserId, e.TeamId}); @@ -36,16 +37,26 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .WithMany(e => e.Tags) .HasForeignKey(e => e.HackathonId); + modelBuilder.Entity() + .HasOne(e => e.Tag) + .WithMany(e => e.Users) + .HasForeignKey(e => e.TagId); + modelBuilder.Entity() .HasOne(e => e.User) .WithMany(e => e.Tags) .HasForeignKey(e => e.UserId); - modelBuilder.Entity() + modelBuilder.Entity() .HasOne(e => e.Tag) - .WithMany(e => e.Users) + .WithMany(e => e.Teams) .HasForeignKey(e => e.TagId); + modelBuilder.Entity() + .HasOne(e => e.Team) + .WithMany(e => e.Tags) + .HasForeignKey(e => e.TeamId); + modelBuilder.Entity() .HasOne(e => e.User) .WithMany(e => e.Teams) @@ -79,11 +90,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasOne(e => e.Organization) .WithMany(e => e.Hackathons) .HasForeignKey(e => e.OrganizationId); - - modelBuilder.Entity() - .HasOne(e => e.Hackathon) - .WithMany(e => e.Tracks) - .HasForeignKey(e => e.HackathonId); } } } From 39a91cd552f19329ef81d9f55bf5b7a6cc4eee2a Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 14:21:38 +0300 Subject: [PATCH 22/56] Fix HackathonFilter Dto --- MethodologyMain.Application/DTO/HackathonFilterDto.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.Application/DTO/HackathonFilterDto.cs b/MethodologyMain.Application/DTO/HackathonFilterDto.cs index abb135c..ddaf5f0 100644 --- a/MethodologyMain.Application/DTO/HackathonFilterDto.cs +++ b/MethodologyMain.Application/DTO/HackathonFilterDto.cs @@ -10,9 +10,9 @@ public class HackathonFilterDto public int? MaxTeamSize { get; set; } - public DateTime? StartDateFrom { get; set; } + public DateOnly? StartDateFrom { get; set; } - public DateTime? StartDateTo { get; set; } + public DateOnly? StartDateTo { get; set; } public int Page { get; set; } = 1; public int PageSize { get; set; } = 10; } From 924b0ffef8ff027390948fe64b4635aecb0b4a2a Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 14:22:18 +0300 Subject: [PATCH 23/56] Add new migrations --- .../20250426165549_Init1.Designer.cs | 464 ++++++++++++++++++ .../Migrations/20250426165549_Init1.cs | 308 ++++++++++++ .../20250426165819_Init2.Designer.cs | 464 ++++++++++++++++++ .../Migrations/20250426165819_Init2.cs | 115 +++++ .../Migrations/MyDbContextModelSnapshot.cs | 127 +++-- 5 files changed, 1439 insertions(+), 39 deletions(-) create mode 100644 MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs diff --git a/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs new file mode 100644 index 0000000..8ca7779 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.Designer.cs @@ -0,0 +1,464 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250426165549_Init1")] + partial class Init1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackthonTag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs new file mode 100644 index 0000000..83246f6 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165549_Init1.cs @@ -0,0 +1,308 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "track", + schema: "mainSchema"); + + migrationBuilder.RenameColumn( + name: "Telegram", + schema: "mainSchema", + table: "teamMember", + newName: "telegram"); + + migrationBuilder.RenameColumn( + name: "linkToWebsite", + schema: "mainSchema", + table: "organization", + newName: "logo"); + + migrationBuilder.RenameColumn( + name: "additionalInfo", + schema: "mainSchema", + table: "hackathon", + newName: "website"); + + migrationBuilder.AddColumn( + name: "createdAt", + schema: "mainSchema", + table: "teamMember", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "github", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "location", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "photoUrl", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "skills", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "website", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AlterColumn( + name: "startDate", + schema: "mainSchema", + table: "hackathon", + type: "date", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "prize", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric"); + + migrationBuilder.AlterColumn( + name: "endDate", + schema: "mainSchema", + table: "hackathon", + type: "date", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AddColumn( + name: "description", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "imageUrl", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "location", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "schedule", + schema: "mainSchema", + table: "hackathon", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.CreateTable( + name: "teamTag", + schema: "mainSchema", + columns: table => new + { + teamId = table.Column(type: "uuid", nullable: false), + tagId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_teamTag", x => new { x.tagId, x.teamId }); + table.ForeignKey( + name: "FK_teamTag_tag_tagId", + column: x => x.tagId, + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_teamTag_team_teamId", + column: x => x.teamId, + principalSchema: "mainSchema", + principalTable: "team", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_teamTag_teamId", + schema: "mainSchema", + table: "teamTag", + column: "teamId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "teamTag", + schema: "mainSchema"); + + migrationBuilder.DropColumn( + name: "createdAt", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "github", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "location", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "photoUrl", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "skills", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "website", + schema: "mainSchema", + table: "teamMember"); + + migrationBuilder.DropColumn( + name: "description", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "imageUrl", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "location", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.DropColumn( + name: "schedule", + schema: "mainSchema", + table: "hackathon"); + + migrationBuilder.RenameColumn( + name: "telegram", + schema: "mainSchema", + table: "teamMember", + newName: "Telegram"); + + migrationBuilder.RenameColumn( + name: "logo", + schema: "mainSchema", + table: "organization", + newName: "linkToWebsite"); + + migrationBuilder.RenameColumn( + name: "website", + schema: "mainSchema", + table: "hackathon", + newName: "additionalInfo"); + + migrationBuilder.AlterColumn( + name: "startDate", + schema: "mainSchema", + table: "hackathon", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateOnly), + oldType: "date"); + + migrationBuilder.AlterColumn( + name: "prize", + schema: "mainSchema", + table: "hackathon", + type: "numeric", + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "endDate", + schema: "mainSchema", + table: "hackathon", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateOnly), + oldType: "date"); + + migrationBuilder.CreateTable( + name: "track", + schema: "mainSchema", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + hackathonId = table.Column(type: "uuid", nullable: false), + trackAdditionalInfo = table.Column(type: "text", nullable: false), + trackName = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_track", x => x.id); + table.ForeignKey( + name: "FK_track_hackathon_hackathonId", + column: x => x.hackathonId, + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_track_hackathonId", + schema: "mainSchema", + table: "track", + column: "hackathonId"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs new file mode 100644 index 0000000..832fc21 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.Designer.cs @@ -0,0 +1,464 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250426165819_Init2")] + partial class Init2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs new file mode 100644 index 0000000..55950ef --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250426165819_Init2.cs @@ -0,0 +1,115 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class Init2 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + table: "hackthonTag"); + + migrationBuilder.DropForeignKey( + name: "FK_hackthonTag_tag_tagId", + table: "hackthonTag"); + + migrationBuilder.DropPrimaryKey( + name: "PK_hackthonTag", + table: "hackthonTag"); + + migrationBuilder.RenameTable( + name: "hackthonTag", + newName: "hackathonTag", + newSchema: "mainSchema"); + + migrationBuilder.RenameIndex( + name: "IX_hackthonTag_hackathonId", + schema: "mainSchema", + table: "hackathonTag", + newName: "IX_hackathonTag_hackathonId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_hackathonTag", + schema: "mainSchema", + table: "hackathonTag", + columns: new[] { "tagId", "hackathonId" }); + + migrationBuilder.AddForeignKey( + name: "FK_hackathonTag_hackathon_hackathonId", + schema: "mainSchema", + table: "hackathonTag", + column: "hackathonId", + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_hackathonTag_tag_tagId", + schema: "mainSchema", + table: "hackathonTag", + column: "tagId", + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_hackathonTag_hackathon_hackathonId", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.DropForeignKey( + name: "FK_hackathonTag_tag_tagId", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.DropPrimaryKey( + name: "PK_hackathonTag", + schema: "mainSchema", + table: "hackathonTag"); + + migrationBuilder.RenameTable( + name: "hackathonTag", + schema: "mainSchema", + newName: "hackthonTag"); + + migrationBuilder.RenameIndex( + name: "IX_hackathonTag_hackathonId", + table: "hackthonTag", + newName: "IX_hackthonTag_hackathonId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_hackthonTag", + table: "hackthonTag", + columns: new[] { "tagId", "hackathonId" }); + + migrationBuilder.AddForeignKey( + name: "FK_hackthonTag_hackathon_hackathonId", + table: "hackthonTag", + column: "hackathonId", + principalSchema: "mainSchema", + principalTable: "hackathon", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_hackthonTag_tag_tagId", + table: "hackthonTag", + column: "tagId", + principalSchema: "mainSchema", + principalTable: "tag", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs index 28f56a3..a2dfc55 100644 --- a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -29,15 +29,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("id"); - b.Property("AdditionalInfo") + b.Property("Description") .IsRequired() .HasColumnType("text") - .HasColumnName("additionalInfo"); + .HasColumnName("description"); - b.Property("EndDate") - .HasColumnType("timestamp with time zone") + b.Property("EndDate") + .HasColumnType("date") .HasColumnName("endDate"); + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + b.Property("MaxTeamSize") .HasColumnType("integer") .HasColumnName("maxTeamSize"); @@ -55,14 +65,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("organizationId"); - b.Property("Prize") - .HasColumnType("numeric") + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") .HasColumnName("prize"); - b.Property("StartDate") - .HasColumnType("timestamp with time zone") + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") .HasColumnName("startDate"); + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + b.HasKey("Id"); b.HasIndex("OrganizationId"); @@ -84,7 +105,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HackathonId"); - b.ToTable("hackthonTag"); + b.ToTable("hackathonTag", "mainSchema"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => @@ -99,10 +120,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("description"); - b.Property("LinkToWebSite") + b.Property("Logo") .IsRequired() .HasColumnType("text") - .HasColumnName("linkToWebsite"); + .HasColumnName("logo"); b.Property("Name") .IsRequired() @@ -172,32 +193,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("team", "mainSchema"); }); - modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => { - b.Property("Id") - .ValueGeneratedOnAdd() + b.Property("TagId") .HasColumnType("uuid") - .HasColumnName("id"); + .HasColumnName("tagId"); - b.Property("HackathonId") + b.Property("TeamId") .HasColumnType("uuid") - .HasColumnName("hackathonId"); - - b.Property("TrackAdditionalInfo") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trackAdditionalInfo"); + .HasColumnName("teamId"); - b.Property("TrackName") - .IsRequired() - .HasColumnType("text") - .HasColumnName("trackName"); + b.HasKey("TagId", "TeamId"); - b.HasKey("Id"); - - b.HasIndex("HackathonId"); + b.HasIndex("TeamId"); - b.ToTable("track", "mainSchema"); + b.ToTable("teamTag", "mainSchema"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => @@ -211,6 +221,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone") .HasColumnName("birthDate"); + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + b.Property("Education") .IsRequired() .HasColumnType("text") @@ -221,26 +235,51 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("firstName"); + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + b.Property("LastName") .IsRequired() .HasColumnType("text") .HasColumnName("lastName"); - b.Property("Surname") + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") .IsRequired() .HasColumnType("text") .HasColumnName("middleName"); + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + b.Property("Telegram") .IsRequired() .HasColumnType("text") - .HasColumnName("Telegram"); + .HasColumnName("telegram"); b.Property("UserName") .IsRequired() .HasColumnType("text") .HasColumnName("userName"); + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + b.HasKey("Id"); b.ToTable("teamMember", "mainSchema"); @@ -325,15 +364,23 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Hackathon"); }); - modelBuilder.Entity("MethodologyMain.Logic.Entities.TrackEntity", b => + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => { - b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") - .WithMany("Tracks") - .HasForeignKey("HackathonId") + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Hackathon"); + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => @@ -379,8 +426,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Tags"); b.Navigation("Teams"); - - b.Navigation("Tracks"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => @@ -392,12 +437,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Navigation("Hacksthons"); + b.Navigation("Teams"); + b.Navigation("Users"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => { b.Navigation("Members"); + + b.Navigation("Tags"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => From 977f8b4ecda06d07efe52164648dce4adf077ca4 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:44:28 +0300 Subject: [PATCH 24/56] Update Dto --- MethodologyMain.Application/DTO/CreateTeamDto.cs | 8 ++++++-- MethodologyMain.Application/DTO/GetTeamDto.cs | 6 ++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/MethodologyMain.Application/DTO/CreateTeamDto.cs b/MethodologyMain.Application/DTO/CreateTeamDto.cs index e442c52..592925a 100644 --- a/MethodologyMain.Application/DTO/CreateTeamDto.cs +++ b/MethodologyMain.Application/DTO/CreateTeamDto.cs @@ -2,8 +2,12 @@ { public class CreateTeamDto { + public Guid HackathonId { get; set; } public required string Name { get; set; } - public required string Description { get; set; } - public Guid EventId { get; set; } + public string Description { get; set; } = string.Empty; + public List Tags { get; set; } = null!; + public List Members { get; set; } = null!; + public required int MaxMembers { get; set; } + public Guid CreatedBy { get; set; } } } diff --git a/MethodologyMain.Application/DTO/GetTeamDto.cs b/MethodologyMain.Application/DTO/GetTeamDto.cs index 19da396..6816fd4 100644 --- a/MethodologyMain.Application/DTO/GetTeamDto.cs +++ b/MethodologyMain.Application/DTO/GetTeamDto.cs @@ -1,8 +1,6 @@ -using MethodologyMain.Logic.Entities; - -namespace MethodologyMain.Application.DTO +namespace MethodologyMain.Application.DTO { - class GetTeamDto + public class GetTeamDto { public Guid Id { get; set; } public Guid HackathonId { get; set; } From 8d318b3cc2a8ef392883f30b7bd5e5454d70c26c Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:45:21 +0300 Subject: [PATCH 25/56] Update Entity with migration --- MethodologyMain.Logic/Entities/TeamEntity.cs | 3 + .../20250427122659_TeamEntityFix.Designer.cs | 468 ++++++++++++++++++ .../20250427122659_TeamEntityFix.cs | 31 ++ .../Migrations/MyDbContextModelSnapshot.cs | 4 + 4 files changed, 506 insertions(+) create mode 100644 MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs diff --git a/MethodologyMain.Logic/Entities/TeamEntity.cs b/MethodologyMain.Logic/Entities/TeamEntity.cs index 4b95e09..ee45c58 100644 --- a/MethodologyMain.Logic/Entities/TeamEntity.cs +++ b/MethodologyMain.Logic/Entities/TeamEntity.cs @@ -21,6 +21,9 @@ public class TeamEntity [Column("captainId")] public required Guid CaptainId { get; set; } + + [Column("maxMembers")] + public int MaxMembers { get; set; } [Column("teamCreatedAt")] public DateTime TeamCreatedAt { get; set; } = DateTime.UtcNow; diff --git a/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs new file mode 100644 index 0000000..58908cf --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.Designer.cs @@ -0,0 +1,468 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250427122659_TeamEntityFix")] + partial class TeamEntityFix + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs new file mode 100644 index 0000000..1b20c15 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250427122659_TeamEntityFix.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class TeamEntityFix : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "maxMembers", + schema: "mainSchema", + table: "team", + type: "integer", + nullable: false, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "maxMembers", + schema: "mainSchema", + table: "team"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs index a2dfc55..d7eea77 100644 --- a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -177,6 +177,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("hackathonId"); + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + b.Property("Name") .IsRequired() .HasColumnType("text") From b2fbad58df18d40cd69cc699c932e14b82130305 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:46:28 +0300 Subject: [PATCH 26/56] Fix TeamRepository access and add getTeamByHackathon --- .../Interfaces/ITeamRepository.cs | 3 +- .../Repository/TeamRepository.cs | 36 ++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index 9700f21..029a49b 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -1,5 +1,4 @@ using MethodologyMain.Logic.Entities; -using System.Threading.Tasks; namespace MethodologyMain.Persistence.Interfaces { @@ -11,7 +10,7 @@ public interface ITeamRepository : IGenericRepository Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token); Task GetCaptainIdAsync(Guid teamId, CancellationToken token); Task GetHackathonIdAsync(Guid teamId, CancellationToken token); - Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); Task UpdateTeamAsync(TeamEntity team, CancellationToken token); Task> GetTeamsAllAsync(CancellationToken token); Task GetTeamAsync(Guid teamId, CancellationToken token); diff --git a/MethodologyMain.Persistence/Repository/TeamRepository.cs b/MethodologyMain.Persistence/Repository/TeamRepository.cs index a31dd6b..72a88b5 100644 --- a/MethodologyMain.Persistence/Repository/TeamRepository.cs +++ b/MethodologyMain.Persistence/Repository/TeamRepository.cs @@ -73,10 +73,22 @@ public async Task TransferCaptainAsync(Guid newCaptainId, Guid teamId, Cancellat var team = await GetTeamNoTrackingAsync(teamId, token); return team.HackathonId; } - public async Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token) + public async Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token) { var team = await GetTeamAsync(teamId, token); - return team.Members.Select(m => m.UserId).ToList(); + return team.Members.Select(m => m.User.UserName).ToList(); + } + public async Task?> GetTeamByHackathonAsync(Guid HackathonId, CancellationToken token) + { + CheckCancellation(token); + var team = await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .Where(m => m.HackathonId == HackathonId) + .ToListAsync(token); + return team; } public async Task UpdateTeamAsync(TeamEntity team, CancellationToken token) { @@ -87,7 +99,12 @@ public async Task UpdateTeamAsync(TeamEntity team, CancellationToken token) public async Task> GetTeamsAllAsync(CancellationToken token) { CheckCancellation(token); - return await _context.Teams.Include(m => m.Members).ToListAsync(token); + return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .ToListAsync(token); } private static void CheckCancellation(CancellationToken token) { @@ -96,14 +113,23 @@ private static void CheckCancellation(CancellationToken token) private async Task GetTeamNoTrackingAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); - return await _context.Teams.Include(m => m.Members) + return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == teamId, token); } public async Task GetTeamAsync(Guid teamId, CancellationToken token) { CheckCancellation(token); - return await _context.Teams.Include(m => m.Members).FirstOrDefaultAsync(m => m.Id == teamId); + return await _context.Teams + .Include(m => m.Members) + .ThenInclude(i => i.User) + .Include(m => m.Tags) + .ThenInclude(i => i.Tag) + .FirstOrDefaultAsync(m => m.Id == teamId); } private async Task SaveChangesAsync(CancellationToken token) { From e5336cab9d87bb3eb9908df9d8c873730779e1e8 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:49:17 +0300 Subject: [PATCH 27/56] Rework teamController to send new Dto --- .../Controllers/TeamController.cs | 10 ++++---- .../Interface/ITeamService.cs | 8 +++--- .../Services/TeamService.cs | 25 ++++++++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index eec4802..873634f 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -39,7 +39,7 @@ public async Task GetDummyData(CancellationToken cancellationToke // Получение списка команд [HttpGet] - public async Task>> GetTeamsAll(CancellationToken token) + public async Task>> GetTeamsAll(CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -55,7 +55,7 @@ public async Task>> GetTeamsAll(CancellationToken // Создание команды [HttpPost] //[Authorize] - public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -65,7 +65,7 @@ public async Task> CreateTeam([FromBody] CreateTeamDto TimeStamp = DateTime.UtcNow }, token); Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + var team = await teamService.CreateTeamAsync(dto, currentUserId, token); return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); //try //{ @@ -79,7 +79,7 @@ public async Task> CreateTeam([FromBody] CreateTeamDto // Получение информации о команде [HttpGet("{id}")] - public async Task> GetTeam(Guid id, CancellationToken token) + public async Task> GetTeam(Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -215,7 +215,7 @@ public async Task RemoveMember(Guid id, Guid userId, CancellationT // Получение списка участников команды [HttpGet("{id}/users")] - public async Task>> GetTeamMembers(Guid id, CancellationToken token) + public async Task>> GetTeamMembers(Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index da11b0b..182e2b6 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -6,11 +6,11 @@ namespace MethodologyMain.Application.Interface public interface ITeamService { Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); - Task CreateTeamAsync(string name, string description, Guid captainId, Guid eventId, CancellationToken token); + Task CreateTeamAsync(CreateTeamDto dto, Guid captainId, CancellationToken token); Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); - Task GetTeamByIdAsync(Guid teamId, CancellationToken token); - Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); - Task> GetTeamAllAsync(CancellationToken token); + Task GetTeamByIdAsync(Guid teamId, CancellationToken token); + Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task> GetTeamAllAsync(CancellationToken token); Task UpdateTeamAsync(UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 91b68f5..9ce56e7 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -25,24 +25,24 @@ public TeamService( } // Создание новой команды - public async Task CreateTeamAsync( - string name, - string description, + public async Task CreateTeamAsync( + CreateTeamDto dto, Guid captainId, Guid HackathonId, CancellationToken token ) { // Проверка, что у пользователя нет другой команды для этого - await validation.CheckUserNotInAnyTeamForHackathonAsync(captainId, HackathonId, token); + await validation.CheckUserNotInAnyTeamForHackathonAsync(captainId, dto.HackathonId, token); // Создание команды var team = new TeamEntity { + Id = Guid.NewGuid(), - Name = name, - Description = description, + HackathonId = dto.HackathonId, + Name = dto.Name, + Description = dto.Description, CaptainId = captainId, - HackathonId = HackathonId, TeamCreatedAt = DateTime.UtcNow }; // Добавление капитана как участника команды @@ -55,6 +55,7 @@ CancellationToken token team.Members.Add(member); await teamRepo.AddAsync(team, token); return mapper.Map(team); + return mapper.Map(team); } // Удаление команды (только капитаном или администратором) @@ -136,26 +137,26 @@ CancellationToken token await teamRepo.TransferCaptainAsync(newCaptainId, teamId, token); } // Получение информации о команде по ID - public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) + public async Task GetTeamByIdAsync(Guid teamId, CancellationToken token) { await validation.CheckTeamExistsAsync(teamId, token); var team = await teamRepo.GetTeamAsync(teamId, token); - return mapper.Map(team); + return mapper.Map(team); } // Получение списка участников команды - public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) + public async Task> GetTeamMembersAsync(Guid teamId, CancellationToken token) { await validation.CheckTeamExistsAsync(teamId, token); return await teamRepo.GetTeamMembersAsync(teamId, token); } // Получение списка команд - public async Task> GetTeamAllAsync(CancellationToken token) + public async Task> GetTeamAllAsync(CancellationToken token) { var teams = await teamRepo.GetTeamsAllAsync(token); //return mapper.Map>(teams); - return mapper.ProjectTo(teams.AsQueryable()).ToList(); + return mapper.ProjectTo(teams.AsQueryable()).ToList(); } //// Проверка, является ли пользователь капитаном команды From caded37230660b0a6395de15fdbb33e17528a64f Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:49:45 +0300 Subject: [PATCH 28/56] Add TagRepository for teamService --- .../Services/TeamService.cs | 6 +- .../Interfaces/ITagRepository.cs | 7 ++ .../Repository/TagRepository.cs | 72 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 MethodologyMain.Persistence/Interfaces/ITagRepository.cs create mode 100644 MethodologyMain.Persistence/Repository/TagRepository.cs diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 9ce56e7..655dde9 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -12,14 +12,17 @@ namespace MethodTeams.Services public class TeamService: ITeamService { private readonly ITeamRepository teamRepo; + private readonly ITagRepository tagRepo; private readonly ITeamValidationService validation; private readonly IMapper mapper; public TeamService( ITeamRepository teamRepo, + ITagRepository tagRepo, ITeamValidationService validation, IMapper mapper) { this.teamRepo = teamRepo; + this.tagRepo = tagRepo; this.validation = validation; this.mapper = mapper; } @@ -28,7 +31,6 @@ public TeamService( public async Task CreateTeamAsync( CreateTeamDto dto, Guid captainId, - Guid HackathonId, CancellationToken token ) { @@ -54,7 +56,7 @@ CancellationToken token }; team.Members.Add(member); await teamRepo.AddAsync(team, token); - return mapper.Map(team); + await tagRepo.AddTeamTags(team.Id, dto.Tags, token); return mapper.Map(team); } diff --git a/MethodologyMain.Persistence/Interfaces/ITagRepository.cs b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs new file mode 100644 index 0000000..67b9276 --- /dev/null +++ b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs @@ -0,0 +1,7 @@ +namespace MethodologyMain.Persistence.Interfaces +{ + public interface ITagRepository + { + Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token); + } +} \ No newline at end of file diff --git a/MethodologyMain.Persistence/Repository/TagRepository.cs b/MethodologyMain.Persistence/Repository/TagRepository.cs new file mode 100644 index 0000000..2408094 --- /dev/null +++ b/MethodologyMain.Persistence/Repository/TagRepository.cs @@ -0,0 +1,72 @@ +using MethodologyMain.Logic.Entities; +using MethodologyMain.Persistence.Interfaces; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; + +namespace MethodologyMain.Persistence.Repository +{ + public class TagRepository : GenericRepository, ITagRepository + { + private readonly ITeamRepository teamRepo; + public TagRepository(MyDbContext context, ITeamRepository teamRepo) : base(context) + { + this.teamRepo = teamRepo; + } + + public async Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var team = await teamRepo.GetByIdAsync(teamId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "team") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + var tagUserRelations = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!team.Tags.Any(t => t.TagId == tag.Id)) + { + team.Tags.Add(new TeamTagEntity + { + TeamId = teamId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "team" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + tagUserRelations.Add(new TeamTagEntity + { + TeamId = teamId, + Tag = newTag + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } + } +} From 535860331b60fffa46117a948b24ef788c9df916 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:50:34 +0300 Subject: [PATCH 29/56] Add automapper for new teamDto --- MethodologyMain.API/Program.cs | 8 ++++++++ .../Profiles/TeamProfile.cs | 15 ++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index e491a75..6d20df1 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -18,6 +18,7 @@ using MethodologyMain.API.Extensions; using Microsoft.Extensions.Options; using MethodologyMain.Application.DTO; +using MethodologyMain.Logic.Entities; var builder = WebApplication.CreateBuilder(args); @@ -35,10 +36,17 @@ var configuration = new MapperConfiguration(static cfg => { cfg.AddMaps(Assembly.GetExecutingAssembly()); + cfg.CreateMap() + .ForMember(dto => dto.CreatedBy, conf => conf.MapFrom(t => t.CaptainId)) + .ForMember(dto => dto.Members, conf => conf.MapFrom(t => t.Members.Select(s => s.User.UserName).ToList())) + .ForMember(dto => dto.Tags, conf => conf.MapFrom(t => t.Tags.Select(s => s.Tag.TagName).ToList())) + .ForMember(dto => dto.CreatedAt, conf => conf.MapFrom(t => t.TeamCreatedAt)); + cfg.AllowNullCollections = true; cfg.AddGlobalIgnore("Item"); } ); +configuration.AssertConfigurationIsValid(); IMapper mapper = configuration.CreateMapper(); builder.Services.AddSingleton(mapper); diff --git a/MethodologyMain.Application/Profiles/TeamProfile.cs b/MethodologyMain.Application/Profiles/TeamProfile.cs index ef6d157..ab75b33 100644 --- a/MethodologyMain.Application/Profiles/TeamProfile.cs +++ b/MethodologyMain.Application/Profiles/TeamProfile.cs @@ -2,11 +2,6 @@ using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; using MethodTeams.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MethodologyMain.Application.Profiles { @@ -14,14 +9,12 @@ public class TeamProfile : Profile { public TeamProfile() { - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(t => t.CreatedAt, conf => conf.MapFrom(t => t.TeamCreatedAt)); - CreateProjection() - .ForMember(dto => dto.MemberCount, conf => conf.MapFrom(t => t.Members.Count)); - CreateMap() - .ForMember(dto => dto.MemberCount, conf => conf.MapFrom(t => t.Members.Count)); + CreateMap() + .ForMember(t => t.TeamCreatedAt, conf => conf.MapFrom(t => t.CreatedAt)); } } } From 4ac819c000096cdd58d15765ed68a08c756c8111 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Sun, 27 Apr 2025 17:51:29 +0300 Subject: [PATCH 30/56] Fix not implemented controller to send nothing --- MethodologyMain.API/Controllers/UserController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index 9afc49e..c05949a 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -32,8 +32,8 @@ public async Task> CreateTeam([FromBody] CreateTeamDto dto, C TimeStamp = DateTime.UtcNow }); Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); - return Ok(team); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(); } private Guid GetCurrentUserId() From 65edb4c2cf40c77cd4ec8facc06324960cd2b78c Mon Sep 17 00:00:00 2001 From: wer3454 <50406606+wer3454@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:17:38 +0300 Subject: [PATCH 31/56] Update dotnet-desktop.yml --- .github/workflows/dotnet-desktop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index 9a1a036..ad21d28 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -7,7 +7,7 @@ on: jobs: build: - runs-on: shimmer-jaspilite + runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v2 From 499ef83c4b4eae4b12e0a951b7ece45aefbcb959 Mon Sep 17 00:00:00 2001 From: wer3454 <50406606+wer3454@users.noreply.github.com> Date: Sun, 27 Apr 2025 18:42:02 +0300 Subject: [PATCH 32/56] Update dotnet-desktop.yml --- .github/workflows/dotnet-desktop.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index ad21d28..eca883b 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -4,6 +4,8 @@ on: pull_request: branches: [main] workflow_dispatch: +env: + DOTNET_INSTALL_DIR: "./.dotnet" jobs: build: @@ -19,14 +21,14 @@ jobs: # - name: Generate appsettings.json # run: | - # (Get-Content ./AuthMetodology/appsettings.Template.json) -replace '#{POSTGRES_CONNECTION_STRING}#', '${{ secrets.POSTGRES_CONNECTION_STRING }}' -replace '#{GOOGLE_CLIENT_ID}#', '${{ secrets.GOOGLE_CLIENT_ID }}' -replace '#{JWT_SECRET_KEY}#', '${{ secrets.JWT_SECRET_KEY }}' | Set-Content ./AuthMetodology/appsettings.json + # (Get-Content ./MeethodologyMain.API/appsettings.Template.json) -replace '#{POSTGRES_CONNECTION_STRING}#', '${{ secrets.POSTGRES_CONNECTION_STRING }}' -replace '#{GOOGLE_CLIENT_ID}#', '${{ secrets.GOOGLE_CLIENT_ID }}' -replace '#{JWT_SECRET_KEY}#', '${{ secrets.JWT_SECRET_KEY }}' | Set-Content ./AuthMetodology/appsettings.json # shell: pwsh - name: Restore dependencies - run: dotnet restore --verbosity quiet + run: dotnet restore --verbosity quiet ./MethodologyMain.sln - name: Build without warnings - run: dotnet build --configuration Release --no-restore + run: dotnet build --configuration Release --no-restore ./MethodologyMain.sln # - name: Run tests # run: dotnet test --verbosity normal From 0b8da2656149cdc2daeee773f39e476d4587cb5b Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 16:44:18 +0300 Subject: [PATCH 33/56] Important! Change controller route Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/TeamController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 9d780da..6836e26 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -10,7 +10,7 @@ namespace MethodologyMain.API.Controllers { [ApiController] - [Route("api/[controller]")] + [Route("api/main/[controller]")] public class TeamController : ControllerBase { private readonly ITeamService teamService; From f5991468e1bd6dea846f2ebdf4255748d99b32da Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 16:44:52 +0300 Subject: [PATCH 34/56] Update class libs Signed-off-by: BelugaChan --- .../DLL/RabbitMqListener.dll | Bin 13312 -> 13312 bytes .../DLL/RabbitMqPublisher.dll | Bin 10240 -> 10752 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqListener.dll index 91b9c2cccc0073b30c72504709c1d4ebd118976a..4ce721a09a2c7f2825d58d44fe658b23935c0c5f 100644 GIT binary patch delta 3972 zcmZ`+3viUx6+ZX=|K8nyU+g2hkPswmUJD7aBCQaFArLeVK%Vjl1yT&p6eNMExCy)A zB`S=@-x;K6OQcK*1B^B@D$YP?p^OC`r_y#DTBa$2kHOlEeSwJm?%5;+$NriB`_Db+ zJLjHr@A>ckNv%k&cy5RJKwf=&>&|R>w7T`sBmVi-L=O|LB}DZ`Yb@+d5qU9ART0g$ zW3t$uFAC-BMfPT~DRURt`l`S!$w9^UfHas$*ssCcA!eOf096#hR z?xJW>!{}=eM*mm;QGaF!etO0pE7L8^^qcV{N<=Tlv?zMSz7Q&@}beYJ6A=*FmBpte3hjxS<@yQTI zOqQ8FA!N|eTmTR0l}&?mNJmJ#U4Xf{72Gz3+{qkt6 zun)Tjt4cj-mHn=JNRI1P1WO}=t~mO|y><#9>L>&~hyEN;4}GM%X~{{ibJp z(k+AT<{TtKmkPoj8T2%x1<;$9kZ6-`o%nR55WOYB-k`U1!B^jWBNJ$TGwwh$uN@6r z*cbA}$3Pe{Q4ZrX-r>y;dgRbs+;-_s z33}`k-n$kOl|717(BmnTbQQufWCzc_>uyNvptEtKvoHsNNz|*~2fcoQ;KO<+w#RHdhP!6`5x* z_fHk`?PLC_Y5|n-8oR_F&11)b{X9`hKTo}#^X!QOs^Gb6!2a<~Se@KWM4#a4)$*+M z4J+3yZ`76iGlM9uE0{BjvLi$REk87;vK-H1jN{5)6BsWR+D8K4Prj|VN>a4MG0vsv z9ODGj?;1cq#OtN#m^oZ2`jsQYsc0DERa46b%PGcXtf^q%J&e26PDGn+j&r#wZcIaj z1;+czPX*34D@1=%0Trcj*8Zd`i(Vm*rRWow6*a>_(TkW~(G`%87U@9GbGUrAZnt!x zL#oa4Q@v{reBU&*SGQB+HO3mJj#kI=dmOEatcHA^RssLb@gt%Ua=vKpH%n6Id%(F3xLfQ1 zZg%O=Gie*}3>5;qXg1Kxp?eeEY3Ow(`mN)SVmGYm>$L9)BS%P@o}w4I~4Xf@x z1zJSoR4Wh=Xeur5FaiPDBd4tga7apQp0-|O{&%4LRAgw<+TnT50mI0CPpD+!gCK6R8* zOoYvH;A>VD@F_KyGAL}W1ZqtNJ*6I}d%<}Qs5SS3vzI>QXmQV4$c+%F63QU%5}nHDom_#qxjPCS6JsclUMNA4RegCF{rLU)|x$ZOzI?bh)T}A zjoz_xM5TD%2;dNT!^(r)X$e?&%DBkJ#HAvS^u&3z%PK_#!^{&Iq+@2#Zfl-srH%4{ zC}!p;%}mlLrgqa!@t)|$C+KJ50XCO&pzg!n)P zdC`KrT$!R2ukBmnsL>_6X_dSxL+D125uyk%MytuC@`0^JA=S`ORf3j3XO!SG_X2P* zeF@B^o4_I}HB0C|nhqRGHNZ)<0$8o}Nt%VnBw9+DYBGmg%JNc{>ljniNR4KS5_H_$ zLR)~_SicYYljc6wx3OkFTMw|@39Hx9$<|Y>`3+mouzZ>2E0oj~kZ7a@4ib6-L+A-& zLhC0$|B7P*>-UMh(4S&G;p_oNYEBvB64unR+``z&np1K=`Bjd=d_(hV8Cw|JjMWRF zI>m!7Mqz4FjIoTd*3=FF_t+v9AgV(8)FxvP_WwTGQ*xN67}KW*kqiwpUtdJ zc8KG`kRCZkE|n|gVTpxhJ19NZMI0XZaqPSPA%Bh|PkwyqirO{H>&okv*4H+4yq9gb?vK<`J^mKcqd2Y_s16;r9^aaGjF434 zf4BbR?1ir$es%HnO^ZjZOLTmcw@3^xb^2YAVCrQNsto0%g^j_~wzQOL?-l*QI(u2c zgIVDmS7?miFJ&Z@IwSqrQU>ds_()G}vkw)F2?cYMHv4<6@VZ5utG`NO z>U4=*7U8~7g`0mHFu7CJfXp#4LDbXClSWfhs)*6iWG!c2=UoRnA zUZo~6Inz)SwDzKcNxj! zomph0Q;EKgR=gcJd(2mnl( zBCiUHvOXR3cwIKAdvBtXC`BfwyBgKQgEA2Dj9Fc26gXEbU*hX zMtCOFG7@Dy7F!R`QjJ2Yk?D7tVLZC(lx&AR!_x{_EK`Y@vO(Q@6N6ZUXR|Wxi=N35 zr}Q}+Q<0{t8S$3%S&d*}eXrtK8o0}B$Od{vyvygx-}LCo6Iq`EM%aNjS35y9cl+Jp ziK=&@OzEGcyHUNt{#m*)OP8AE)%DSL8}F74VAytyU%2gG$E5o#Ijoo0JGwAF%f1pb zbV~)>upP$4|CxDSpc8k>Oy6xow3M%BX*WpZ2u*8mQjvi zxWb+t8whdXpaDB?$#a#K-$LbzxEZKC61RWy53x3BTZpdUej7VGZT^P!HEUn3Q#0vK z;1@z^3+K}r*l}t$#S2S|aQ__sBZs}yH(4yP&-=zjb{jlPGH8+`$!X95#v%GwW-Lv_ zt~RJuHw=SzI=%)v82_Lv`x@gijuf&T;@XXjb;fF_y{soWU8HLx!5^<3HoPRwM$1o~ z#vMn1lB`I?nM}W;TcCC$ZBPXY4BCM926cgC&~j2jYgtZkc7>&cwi}I>mr9&tEQ5Aw zs_ML{@C;*~sniPCKE!I}Z0{n)c@^lTi&mo*@lr8_3`#XJXQ3Kw)>}{g}*_uh;4#-)gtK)=v z#BZ=MESibKM0p3aRCu%5+s-O3Do=|%qq-;@dPa58NcN&sH|6%_l&G6lZTvC z7iD^ALtjoYJv0SJ)l;U23fYS?V`yd;eV>zx8beO}VSY+gr=y_ZSZ0B(7#An7sg%7+ zi;I(eb~M|J%`NfrRQ4G2{}0*+1H&RWOhGz4#{(FkB1jbWU~Sio4yIG3@4u?i@t z2AD{j8IJ>#sS9XegD4cd-h$V8gisO1%%nZQQTX(3L=f`ODMvm9#XYSE_@*@jSZyq( z1iGiy097P`s*O!F2AsEmDl!I~Hu{p=w9-xE1l5Qq;zL?Tm(0^-iO=N;aJuAq*fm(n zb>bFw@*YySS^UXy9obwnauc^Yq=QTiB6JhBitM3QsUAW}l=8E8&^uPDC>3k9I2=5m%0(+Jl>0LCbk=%99u%p@n}}R@w8{H4LH<%+g2DkA@$o|Wc!`ok0H5k{@e}PRNYmvB>BkPd z222D7X$@U*qyww9Oj=40968wZ`?MU2r+0xVbQ+jO7l2vh)pO`O6as#iMgynPB;YF? zpAVc$E9tIdT7>0Rva^!yYQ`q2qhh^@>S?FGjkW<_=Xg8fw%*S14vy^S>^p3qME1IV zlCxbL`G~Wp*#0})H`yjpM>!4>5!FBwszFewnN30BM~*2%#oI+2u#4k_^9CHLI0cN$ zIa0-TGvi5)bjkhnH%F?*d`F@D*HWJh7YTS+UXG8!S`P&7E2As0MQby4JR-D#^Lw=U`hiflYK5ZKXOF8 zCwjz}!XZb?ak5Eb-MIiYed8F;6a4n*AKf^%l`}AQUjCk4Q2WP4*{FWyKga8qcks(| zKnFhIXcLaI=ZWX#EfyTuq+1r-oheh3Y_XI+!1XU&ljKsGgUiNsq%(HNIbnbGQbuR` z&_`xGBwwq|>*=YuT-b8BSX*P=Z0{`3s1%`G)8kC^HT^>POZ}-)V{`P@bkJALme;`Uz(|2F_?S(JI*75f3?73t6f{UI8p}pX*Ypz+b`|?(-Y(G)b pgZiiAp|Vq3g8_NB)ZR9#r89MGyXf@he5=X0{7&E4d!qGa^MBwLp6>tv diff --git a/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll b/MethodologyMain.Infrastructure/DLL/RabbitMqPublisher.dll index 114d9437dcf9341bc3dbd037e0865aa7f94b2093..0e1da0a999139fe74eacc1f1b58bfae55ebbe62c 100644 GIT binary patch delta 3518 zcmZuzeQ=b;8Gm-)uiSBj`wU4)n%t3)gME7&b zpM5@epM7@U>t5Ym^TP8FIR-aer*ykQp~4AbHcUad!VVd+k%S*@0?JSd+I z)$LqsgKX059oEzGsBVPxB(#9^*G#ifZWnC8IYCb z&&rZrv%uWEQNetGPxtEK3J^1^Wp=SMp;jV2dZJE^F1fQ5qgVIJFxFE_mqR6pEW4D{ zr^}scydB8Lu4Eu>40j8_wO3{2CgUJBKcRFDuMw^XfhaknQH(?bSff!4L~(MI*Rf{V zrG!31?o{LLz(k@cV?m5?Be>I2Ta;Z9On9Ry(x2L9(z*GE5Ty2Ldd<80%pF~UdG9{W z(S4Ti3V565|KFy`+axKwW+H|^JOL|DG=m&VdvZ%^IkHRf!!0aS=?^~%@MU;2!cQr} z@>=0m5J=9H(WP05O<;{C$HLN3k2r$8q>`hAK1=RYl^A1N7Q$9W8B5Tb24xJ*az(Qy*SSZ-I6zddb7f7Gr!D^K8R@(i!m-VyZ;yX6fi# z>?6*(Nxo;a+`ux>Oe)u(Hcfh&(XVYbC(&Wt43lE#n2o8s>kW z={&aG#5l|N0N#FNT!d{{Q=Si5al=XLtZQZ_H5(U`x|fa_XRR#irDDsZ4`m##*RX0U z!kaXMT|7d{(TG$o4l^z?75x`O>1#|MX8rA?_#1&<5*cSLFFgqVUebUjEo99v3?-dp zowbrCJ;5QvB5ptxERzOkrpTrB<|QMSnygC*&__!8t$9`*3l(s(1PSU#MjxPsI6pP( z!K{jQS=FE=X~IokLAx3cPzKLT*j3|knZPsUq&i6+%A_DAtkpoTQ3cb}hF=KElpbNy z4cUq07nm);Gv+2pD`>_z{s8#T8^=ebGpGl)he>%*nu3nd8{_mphvs_u58zID1DG6d zoWo`*EHS=s( ze1qe1(m+UQ4vV+tOw8WonF?qk)xS&2l;#BbSJ9Z}1p0Ro$4{xc=-aeVsk*3e`k1P^ zB?5_ayCu@C=maWZjN^8TG=DvEA(33STT65P0FI!$s3GY(wWB85LA57Q4lSq)575K| z&|*4iI?zpX7%LfLjLR6;FxE20fr46q0Tka|%%$U?OXw8Pq`xu_liJiUsSF9B_y@tC zOG!T$-ELOOqZ9ga@^dj3F=vFX$p$Lo0xaSJEaH+Jp$pb_8lj-Eo61j|$w3X&*CG;pwG$OcO zOouvq4|oT>_B`)ghhOH&gxn?1+3j9mvJBr_eBno%OSAEUs5fMME5|GJzj_zdXPx*H zr3kcumil6i_xC-mm{rE}O0-MtPbXyGz|!zdg}IJjDdOswr^bx*=uD3;j1N#Z{=c8V zdEKN=l+AP0hCU>Y;#wW0S@I~=q92gw=nO{E>^k2~xv1^z5e6XdhA+~i# zTRp99Y-?EAxOHp1sWHW<-d^7vZ)<8?+*scl?-=@(|0T160&!}^ZzDC}?dzaMMBYX; z@tzr0|8C%;*FV|wiQB;O!oinR!xr?swwae3colUz4R ztX!=Qst&!T3OxiO-PGCn&`Z$YszMLh`wBzu{dbI)K9IYX^?X&ZoDI delta 3029 zcmZ8jdvMi975;Yb?~&XDxQ`@F0!nV4wwmb^qQ9uGH!az;p zP3$xUT5Hqa*az~5k+F_#=%kI(RuN$kW>Bh?))sZFWLl=hVH8@d11k8PlZ(Ob%zk^$ zx96PQ-`TT!Z`b0kmM3@3YdN_5_sF!fC@sk`w*e(2ykW9u7Dv$=*nx=37I0J@8PU~y zx_0zbTHh@*4M1C{HxbWW3FK10ZzixfNZ6X-ep3~Gd_1WV>A@aTmfb)};*|ym&G_t< zl(+yYgZE5n(K=b5?ThRdF0zt9O95bl#Se4N(YZPd1N>*281EU_el6O{VP z?E)Kg``@&0n83|yjMipV!z-$Fs{QJv(=XB}xR6y`x`K{dRubY)%t^LVnAmI!E5e-; z(MFxlRl!SH1?eio!0oHl&UVOnEq@d+*5+qS>Aae3rM2x7Ip!t9Ky~L@injd$;#LOu zifyk|Lg?g!Dozq{9U<<;yySWj+?bo(K!F=6%0!=Qqi*My$=O`nQOz;t#%wZ&OW@Dn zl5cL8$+&AfWW1JN$ux~@%}s73ORK!jwZWs|r167+a6z`8Y!mvuvDEVGlAA=Cz+jDa z!%3{;mZz{k$cz?|ztMaO-Q;%Jpde?;%!^q-**Ab?*}zAfD_gW}>xRwiz9!~PQJ|1x z**%M}jB-TeJMWp>#IcR~2TstFQyZ0{kSVDbIl@iB@tmn?ejZzi%Pp{Z$ae1aJZw`u zZ=1X^*ulg1@IdIW<6)`ub=Sk`kl?o!`xS3hevHbOLK0!NMsVC8P@eA|pznXI@Z0@q zZWuNGA#XJ9a1W%N7#?@``32~~RZjoVPGjgw4bd2CB6Ho55cfgwHyUDxVxcGDo_EFm zj4SdEwciPmR}f=($KU72a0}zdaK_o^dx)#oQQF7wfw#|3d$?VfOqgjdP3hoa0F|Z~ zle_`97%6{%3-m%}e@6$&QlTcxz@U#AorO5hNwjWi4OrqgQ?>}12rkgNS+138*Hz0# zj%pI5c^;w|jRY3@EyNF<2D(1$<{5+cP1JZeX16o>m)#A-?|Pd!I~@~l;s?ktcVCy; z;1{Dlm%d?tj?5(cSK3D&&KSF}?DQqPE5hwV8 z(oVQO)Jd~LeOP2G+@)6Sk%-Cglb8$3tVSZC46~PvfuhCUpmj_< zJ<~HhSlM3@F^pS@5lmLBS8P*)p-<8{haI7;;J2gM=CXAD7d zVvO+5k)Mh@e3)h(?N+04c*>biO6sdznJYMC*HD(4D%YAS*DAY$et##f;8SNeYSglh zmd{hZ><$p6`f9Y+YSg|??dxcN0x7kxH;3$BC|`Ed=QxN%N{cY1MVM0OlseZNS*+fC z>RjdKq}21Y?EA3AEi{d0jTvXYigK^QoJYtOnsP1sE4W~4$?W2H&ow``^2LG+%s!{d zT)}>KF7YYfOLO8^W}T@~w>otz(iHXLm;OVh$Sk!HUg}r;PRc*?4Zmyxx+(XuFq^pW zv*s>cxP~|31WD$>bTf3Ze7Ybr8lSE$QIKnHBIsK^GqL}Fvc#{ zpvyF9O0U;44Vu!+mx5fxgjr}B<#4!sTgFnZV4GTQFg;$6P4UE^w%gF*_t|dKVP3K) zX@A5{Hj<~5Ue?KJBPpskl8}1Cgdm1&{L99WuUMp5L976OLPAwo%J;FBmuX6<7IDlV zj>QsU8CDak(MOz$*N8K4j5r5x66Y(wh&TtUaoTCdM&yKAk=}??&T6GrE45a!3+?z* zs0$CH(s>w<5g$>0zsg5ATkRat*<;F_CDY-YRc1&n8_a%sH5yr_Tk(6!^r?JQ5qAGd z8W}5J)@s#M@u=dEq6rC~P;69eRqPIlSD)fh#l?66zr}UjZBFv7leh0qTN|v1-;s{k zLc7GSvU{!5B`?6ujjtOY{gL*rUC&qIvsT%BX+CRrz!6S=XGCB-YlnY!ZjN`}Ud`hY z|L^><9SA1n-Lj~hdvW;a506=yF`OB5InF{C|49CvCv*whStyTUGy9-<5trDj?TgsX zy6WZlYuz@2Hxq@yPx9Ulp3Gkye3Bm>EGl@$3tk>q5XJ1v$0z>t%)4KB=HMrr>lU6n zHTcoElO|E+XJzF_yB;yI1^KZ;6UVU9)tec=6TI{JdxN{iHxKR~-)g5~&rkQ9hxt;A zEVq)qpZ{q4ODJTTq&Lo9#h%MQt+|O{T4`zI+CM5fcP{In-Ph{W+a2%s2J1@~P05g3 z6B$xsx7Dv-Q}NcuYptg@9bQWR8*RJDCB2CPyKYwCmc1N|E}vl<2IrN(8p`IsQ~6!k OHES@M{JZJB&HpcERsz)k From 5b2258b083d95974f0f4a681199b8e6f6d94b2d0 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 16:45:15 +0300 Subject: [PATCH 35/56] Provide new property Signed-off-by: BelugaChan --- .../Listeners/RabbitMqUserRegisterListener.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs index 70fea0b..96f6589 100644 --- a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -39,7 +39,9 @@ public override async Task ProcessMessageAsync(string message) var context = scope.ServiceProvider.GetRequiredService(); await context.AddAsync(new UserMainEntity { - Id = data.UserId + Id = data.UserId, + UserName = data.UserName, + }); } From 0b428064c9e62171f5067001c4452abceaed2580 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 16:45:42 +0300 Subject: [PATCH 36/56] Add new prop username Signed-off-by: BelugaChan --- .../Models/RabbitMqUserRegisterRecieve.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs index 6c87699..e05c623 100644 --- a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs +++ b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs @@ -6,6 +6,8 @@ public class RabbitMqUserRegisterRecieve : IEvent { public Guid UserId { get; set; } + public string UserName { get; set; } + public string EventType => "RecieveUserRegister"; } } From 91e203240be4177ce2f9f6adbe1151f397d0c776 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 21:29:54 +0300 Subject: [PATCH 37/56] Add new prop email Signed-off-by: BelugaChan --- .../Models/RabbitMqUserRegisterRecieve.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs index e05c623..ea9ca3b 100644 --- a/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs +++ b/MethodologyMain.Infrastructure/Models/RabbitMqUserRegisterRecieve.cs @@ -8,6 +8,8 @@ public class RabbitMqUserRegisterRecieve : IEvent public string UserName { get; set; } + public string Email { get; set; } + public string EventType => "RecieveUserRegister"; } } From ee39f6fdf1df701c19cfbdd496efe3b22f381b14 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 21:30:26 +0300 Subject: [PATCH 38/56] Minor fixes Signed-off-by: BelugaChan --- .../Listeners/RabbitMqUserRegisterListener.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs index 96f6589..825be6d 100644 --- a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -41,7 +41,7 @@ await context.AddAsync(new UserMainEntity { Id = data.UserId, UserName = data.UserName, - + Email = data.Email, }); } From 5485d65d21494933d514a2a798a166ff7aa7450f Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Mon, 28 Apr 2025 21:44:53 +0300 Subject: [PATCH 39/56] add new prop (Email) Signed-off-by: BelugaChan --- MethodologyMain.Logic/Entities/UserMainEntity.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index 10d3b2e..e574eb5 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -13,6 +13,10 @@ public class UserMainEntity public DateTime BirthDate { get; set; } = DateTime.MinValue; [Column("education")] public string Education { get; set; } = string.Empty; + + [Column("email")] + public string Email { get; set; } = string.Empty; + [Column("firstName")] public string FirstName { get; set; } = string.Empty; [Column("lastName")] From ba5e2c92f3302ab86e00afb779b4a8b6e083e719 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Mon, 28 Apr 2025 23:28:25 +0300 Subject: [PATCH 40/56] Add email to UserEntity --- .../Entities/UserMainEntity.cs | 3 + MethodologyMain.Logic/Models/UserMain.cs | 1 + .../20250428193128_AddUserEmail.Designer.cs | 473 ++++++++++++++++++ .../Migrations/20250428193128_AddUserEmail.cs | 31 ++ .../Migrations/MyDbContextModelSnapshot.cs | 5 + 5 files changed, 513 insertions(+) create mode 100644 MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs create mode 100644 MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs diff --git a/MethodologyMain.Logic/Entities/UserMainEntity.cs b/MethodologyMain.Logic/Entities/UserMainEntity.cs index 155cfff..7fdc349 100644 --- a/MethodologyMain.Logic/Entities/UserMainEntity.cs +++ b/MethodologyMain.Logic/Entities/UserMainEntity.cs @@ -25,6 +25,9 @@ public class UserMainEntity [Column("middleName")] public string MiddleName { get; set; } = string.Empty; + [Column("email")] + public string Email { get; set; } = string.Empty; + [Column("userName")] public string UserName { get; set; } = string.Empty; diff --git a/MethodologyMain.Logic/Models/UserMain.cs b/MethodologyMain.Logic/Models/UserMain.cs index a42ac9d..03157dc 100644 --- a/MethodologyMain.Logic/Models/UserMain.cs +++ b/MethodologyMain.Logic/Models/UserMain.cs @@ -18,6 +18,7 @@ public class UserMain public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string MiddleName { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; public string UserName { get; set; } = string.Empty; public string PhotoUrl { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; diff --git a/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs new file mode 100644 index 0000000..ea12941 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.Designer.cs @@ -0,0 +1,473 @@ +// +using System; +using MethodTeams.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + [DbContext(typeof(MyDbContext))] + [Migration("20250428193128_AddUserEmail")] + partial class AddUserEmail + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndDate") + .HasColumnType("date") + .HasColumnName("endDate"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("imageUrl"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MaxTeamSize") + .HasColumnType("integer") + .HasColumnName("maxTeamSize"); + + b.Property("MinTeamSize") + .HasColumnType("integer") + .HasColumnName("minTeamSize"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OrganizationId") + .HasColumnType("uuid") + .HasColumnName("organizationId"); + + b.Property("Prizes") + .IsRequired() + .HasColumnType("text") + .HasColumnName("prize"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("text") + .HasColumnName("schedule"); + + b.Property("StartDate") + .HasColumnType("date") + .HasColumnName("startDate"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("hackathon", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.HasKey("TagId", "HackathonId"); + + b.HasIndex("HackathonId"); + + b.ToTable("hackathonTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("text") + .HasColumnName("logo"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("organization", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("TagClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagClassName"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tagName"); + + b.HasKey("Id"); + + b.ToTable("tag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CaptainId") + .HasColumnType("uuid") + .HasColumnName("captainId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("HackathonId") + .HasColumnType("uuid") + .HasColumnName("hackathonId"); + + b.Property("MaxMembers") + .HasColumnType("integer") + .HasColumnName("maxMembers"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("TeamCreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("teamCreatedAt"); + + b.HasKey("Id"); + + b.HasIndex("HackathonId"); + + b.ToTable("team", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.HasKey("TagId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("teamTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BirthDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthDate"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("createdAt"); + + b.Property("Education") + .IsRequired() + .HasColumnType("text") + .HasColumnName("education"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("MiddleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("middleName"); + + b.Property("PhotoUrl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("photoUrl"); + + b.Property("Skills") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skills"); + + b.Property("Telegram") + .IsRequired() + .HasColumnType("text") + .HasColumnName("telegram"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("userName"); + + b.Property("Website") + .IsRequired() + .HasColumnType("text") + .HasColumnName("website"); + + b.HasKey("Id"); + + b.ToTable("teamMember", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tagId"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.HasKey("TagId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("userTag", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("userId"); + + b.Property("TeamId") + .HasColumnType("uuid") + .HasColumnName("teamId"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joinedAt"); + + b.HasKey("UserId", "TeamId"); + + b.HasIndex("TeamId"); + + b.ToTable("userTeam", "mainSchema"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.OrganizationEntity", "Organization") + .WithMany("Hackathons") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Tags") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Hacksthons") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.HackathonEntity", "Hackathon") + .WithMany("Teams") + .HasForeignKey("HackathonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Hackathon"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Teams") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Tags") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTagEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TagEntity", "Tag") + .WithMany("Users") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Tags") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tag"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserTeamEntity", b => + { + b.HasOne("MethodologyMain.Logic.Entities.TeamEntity", "Team") + .WithMany("Members") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MethodologyMain.Logic.Entities.UserMainEntity", "User") + .WithMany("Teams") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.HackathonEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => + { + b.Navigation("Hackathons"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TagEntity", b => + { + b.Navigation("Hacksthons"); + + b.Navigation("Teams"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.TeamEntity", b => + { + b.Navigation("Members"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("MethodologyMain.Logic.Entities.UserMainEntity", b => + { + b.Navigation("Tags"); + + b.Navigation("Teams"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs new file mode 100644 index 0000000..cb74655 --- /dev/null +++ b/MethodologyMain.Persistence/Migrations/20250428193128_AddUserEmail.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MethodologyMain.Persistence.Migrations +{ + /// + public partial class AddUserEmail : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "email", + schema: "mainSchema", + table: "teamMember", + type: "text", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "email", + schema: "mainSchema", + table: "teamMember"); + } + } +} diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs index d7eea77..b0106d7 100644 --- a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -234,6 +234,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("education"); + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .HasColumnName("email"); + b.Property("FirstName") .IsRequired() .HasColumnType("text") From aaca34e12cb829987661d31833f28f707c955719 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Mon, 28 Apr 2025 23:30:14 +0300 Subject: [PATCH 41/56] Add tagRepository method for user and hackathon --- MethodologyMain.API/Program.cs | 3 + .../Interfaces/ITagRepository.cs | 2 + .../Repository/TagRepository.cs | 122 +++++++++++++++++- 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 6d20df1..2ed637a 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -56,7 +56,10 @@ builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); +builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton, LogQueueService>(); diff --git a/MethodologyMain.Persistence/Interfaces/ITagRepository.cs b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs index 67b9276..6445421 100644 --- a/MethodologyMain.Persistence/Interfaces/ITagRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITagRepository.cs @@ -3,5 +3,7 @@ public interface ITagRepository { Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token); + Task AddUserTags(Guid userId, List tagNames, CancellationToken token); + Task AddHackTags(Guid hackId, List tagNames, CancellationToken token); } } \ No newline at end of file diff --git a/MethodologyMain.Persistence/Repository/TagRepository.cs b/MethodologyMain.Persistence/Repository/TagRepository.cs index 2408094..def0c47 100644 --- a/MethodologyMain.Persistence/Repository/TagRepository.cs +++ b/MethodologyMain.Persistence/Repository/TagRepository.cs @@ -8,9 +8,17 @@ namespace MethodologyMain.Persistence.Repository public class TagRepository : GenericRepository, ITagRepository { private readonly ITeamRepository teamRepo; - public TagRepository(MyDbContext context, ITeamRepository teamRepo) : base(context) + private readonly IUserRepository userRepo; + private readonly IHackathonRepository hackRepo; + public TagRepository( + MyDbContext context, + ITeamRepository teamRepo, + IUserRepository userRepo, + IHackathonRepository hackRepo) : base(context) { this.teamRepo = teamRepo; + this.userRepo = userRepo; + this.hackRepo = hackRepo; } public async Task AddTeamTags(Guid teamId, List tagNames, CancellationToken token) @@ -51,7 +59,7 @@ public async Task AddTeamTags(Guid teamId, List tagNames, CancellationTo // Добавляем связь с новым тегом // (ID тега будет установлен после сохранения) - tagUserRelations.Add(new TeamTagEntity + team.Tags.Add(new TeamTagEntity { TeamId = teamId, Tag = newTag @@ -68,5 +76,115 @@ public async Task AddTeamTags(Guid teamId, List tagNames, CancellationTo // Сохраняем изменения await _context.SaveChangesAsync(token); } + + public async Task AddUserTags(Guid userId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var user = await userRepo.GetByIdAsync(userId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "user") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!user.Tags.Any(t => t.TagId == tag.Id)) + { + user.Tags.Add(new UserTagEntity + { + UserId = userId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "user" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + user.Tags.Add(new UserTagEntity + { + UserId = userId, + Tag = newTag + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } + + public async Task AddHackTags(Guid hackId, List tagNames, CancellationToken token) + { + token.ThrowIfCancellationRequested(); + var hack = await hackRepo.GetByIdAsync(hackId, token); + var existTags = await _context.Tags + .Where(m => m.TagClassName == "hack") + .Where(m => tagNames.Contains(m.TagName)) + .ToDictionaryAsync(m => m.TagName, t => t, cancellationToken: token); + var newTagsToAdd = new List(); + + foreach (var tagName in tagNames) + { + // Если тег уже существует, используем его + if (existTags.TryGetValue(tagName, out var tag)) + { + // Проверяем, что связь еще не существует + if (!hack.Tags.Any(t => t.TagId == tag.Id)) + { + hack.Tags.Add(new HackathonTagEntity + { + HackathonId = hackId, + TagId = tag.Id + }); + } + } + else + { + // Создаем новый тег + var newTag = new TagEntity + { + TagName = tagName, + TagClassName = "hack" + }; + newTagsToAdd.Add(newTag); + + // Добавляем связь с новым тегом + // (ID тега будет установлен после сохранения) + hack.Tags.Add(new HackathonTagEntity + { + HackathonId = hackId, + TagId = tag.Id + }); + } + + } + // Добавляем новые теги в контекст + if (newTagsToAdd.Count != 0) + { + await _context.Tags.AddRangeAsync(newTagsToAdd, token); + } + + // Сохраняем изменения + await _context.SaveChangesAsync(token); + } } } From 8194a4cbc09fa67fb5c9b001882d216c8eb06f5f Mon Sep 17 00:00:00 2001 From: wer3454 Date: Mon, 28 Apr 2025 23:31:25 +0300 Subject: [PATCH 42/56] Rework TeamController and add GetTeamForHackathon --- .../Controllers/TeamController.cs | 300 +++++++----------- .../Interface/ITeamService.cs | 1 + .../Services/TeamService.cs | 9 + .../Interfaces/ITeamRepository.cs | 1 + 4 files changed, 118 insertions(+), 193 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 873634f..f36e4f7 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -52,271 +52,185 @@ public async Task>> GetTeamsAll(CancellationToken return Ok(teams); } - // Создание команды - [HttpPost] - //[Authorize] - public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "POST api/Team was called", - TimeStamp = DateTime.UtcNow - }, token); - Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена - var team = await teamService.CreateTeamAsync(dto, currentUserId, token); - return CreatedAtAction(nameof(GetTeam), new { id = team.Id }, team); - //try - //{ - - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} - } - // Получение информации о команде - [HttpGet("{id}")] - public async Task> GetTeam(Guid id, CancellationToken token) + [HttpGet("hackathon/{hackId}")] + public async Task>> GetTeamsForHackathon(Guid hackId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/Team/id was called", + Message = "GET api/Team/hackathon/id was called", TimeStamp = DateTime.UtcNow }, token); - var team = await teamService.GetTeamByIdAsync(id, token); - return Ok(team); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} + var teams = await teamService.GetTeamForHackathonAsync(hackId, token); + return Ok(teams); } - [HttpPut] + // Создание команды + [HttpPost] //[Authorize] - public async Task UpdateTeam([FromBody] UpdateTeamDto dto, CancellationToken token) + public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "Update api/Team/id was called", + Message = "POST api/Team was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.UpdateTeamAsync(dto, currentUserId, token); - return NoContent(); + // Получение ID текущего пользователя из токена + var team = await teamService.CreateTeamAsync(dto, dto.CreatedBy, token); + return CreatedAtAction(nameof(GetTeamById), new { id = team.Id }, team); } - // Удаление команды - [HttpDelete("{id}")] - //[Authorize] - public async Task DeleteTeam(Guid id, CancellationToken token) + // Получение информации о команде + [HttpGet("{id}")] + public async Task> GetTeamById(Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "DELETE api/Team/id was called", + Message = "GET api/Team/id was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - - await teamService.DeleteTeamAsync(id, currentUserId, token, isAdmin); - return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} + var team = await teamService.GetTeamByIdAsync(id, token); + return Ok(team); } // Добавление пользователя в команду - [HttpPost("{id}/users")] + [HttpPost("{id}/users/{userId}")] //[Authorize] - public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) + public async Task JoinMember(Guid id, Guid userId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team/id/members was called", + Message = "POST api/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); + await teamService.AddUserToTeamAsync(id, userId, userId, token); return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} } // Удаление пользователя из команды [HttpDelete("{id}/users/{userId}")] //[Authorize] - public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) + public async Task LeaveMember(Guid id, Guid userId, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "DELETE api/Team/id/members/userId was called", + Message = "DELETE api/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); + await teamService.RemoveUserFromTeamAsync(id, userId, userId, token); return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} } - // Получение списка участников команды - [HttpGet("{id}/users")] - public async Task>> GetTeamMembers(Guid id, CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "GET api/Team/id/members was called", - TimeStamp = DateTime.UtcNow - }, token); - var members = await teamService.GetTeamMembersAsync(id, token); - return Ok(members); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - } - - // Передача прав капитана - [HttpPut("{id}/captain")] - //[Authorize] - public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) - { - _ = logPublishService.SendEventAsync(new RabbitMqLogPublish - { - ServiceName = "Main service", - LogLevel = LogEventLevel.Information, - Message = "PUT api/Team/id/captain was called", - TimeStamp = DateTime.UtcNow - }, token); - Guid currentUserId = GetCurrentUserId(); - await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); - return NoContent(); - //try - //{ - - //} - //catch (KeyNotFoundException) - //{ - // return NotFound(); - //} - //catch (UnauthorizedAccessException ex) - //{ - // return Forbid(ex.Message); - //} - //catch (InvalidOperationException ex) - //{ - // return BadRequest(ex.Message); - //} - } - - - //// Получение списка команд для события - //[HttpGet("event/{eventId}")] - //public async Task>> GetTeamsByEvent(Guid eventId) + //[HttpPut] + ////[Authorize] + //public async Task UpdateTeam([FromBody] UpdateTeamDto dto, CancellationToken token) //{ - // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish // { // ServiceName = "Main service", // LogLevel = LogEventLevel.Information, - // Message = "GET api/Team/event/eventId was called", + // Message = "Update api/Team/id was called", // TimeStamp = DateTime.UtcNow - // }); - // var teams = await _teamService.GetTeamsByEventIdAsync(eventId); - // return Ok(teams); + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.UpdateTeamAsync(dto, currentUserId, token); + // return NoContent(); //} - //// Получение команды пользователя для конкретного события - //[HttpGet("event/{eventId}/user")] + //// Удаление команды + //[HttpDelete("{id}")] ////[Authorize] - //public async Task> GetUserTeamForEvent(Guid eventId) + //public async Task DeleteTeam(Guid id, CancellationToken token) //{ - // await logQueueService.SendLogEventAsync(new RabbitMqLogPublish + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish // { // ServiceName = "Main service", // LogLevel = LogEventLevel.Information, - // Message = "GET api/Team/event/eventId/user was called", + // Message = "DELETE api/Team/id was called", // TimeStamp = DateTime.UtcNow - // }); + // }, token); // Guid currentUserId = GetCurrentUserId(); - // var team = await _teamService.GetUserTeamForEventAsync(currentUserId, eventId); + // bool isAdmin = User.IsInRole("Admin"); // Проверка роли администратора - // if (team == null) - // { - // return NotFound(); - // } - - // return Ok(team); + // await teamService.DeleteTeamAsync(id, currentUserId, token, isAdmin); + // return NoContent(); + //} - //try + //// Добавление пользователя в команду + //[HttpPost("{id}/users")] + ////[Authorize] + //public async Task AddMember(Guid id, [FromBody] AddUserDto dto, CancellationToken token) //{ - + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "POST api/Team/id/members was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.AddUserToTeamAsync(id, dto.UserId, currentUserId, token); + // return NoContent(); //} - //catch (Exception ex) + + //// Удаление пользователя из команды + //[HttpDelete("{id}/users/{userId}")] + ////[Authorize] + //public async Task RemoveMember(Guid id, Guid userId, CancellationToken token) //{ - // return BadRequest(ex.Message); + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "DELETE api/Team/id/members/userId was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.RemoveUserFromTeamAsync(id, userId, currentUserId, token); + // return NoContent(); //} + + //// Получение списка участников команды + //[HttpGet("{id}/users")] + //public async Task>> GetTeamMembers(Guid id, CancellationToken token) + //{ + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "GET api/Team/id/members was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // var members = await teamService.GetTeamMembersAsync(id, token); + // return Ok(members); //} + //// Передача прав капитана + //[HttpPut("{id}/captain")] + ////[Authorize] + //public async Task TransferCaptainRights(Guid id, [FromBody] AddUserDto dto, CancellationToken token) + //{ + // _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + // { + // ServiceName = "Main service", + // LogLevel = LogEventLevel.Information, + // Message = "PUT api/Team/id/captain was called", + // TimeStamp = DateTime.UtcNow + // }, token); + // Guid currentUserId = GetCurrentUserId(); + // await teamService.TransferCaptainRightsAsync(id, dto.UserId, currentUserId, token); + // return NoContent(); + //} // Вспомогательный метод для получения ID текущего пользователя //private int GetCurrentUserId() //{ @@ -324,9 +238,9 @@ public async Task TransferCaptainRights(Guid id, [FromBody] AddUse // var userIdClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); // return int.Parse(userIdClaim.Value); //} - private Guid GetCurrentUserId() - { - return Guid.Parse("d5a492ca-9611-4fda-9ace-10ec38bb4d48"); - } + //private Guid GetCurrentUserId() + //{ + // return Guid.Parse("d5a492ca-9611-4fda-9ace-10ec38bb4d48"); + //} } } diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index 182e2b6..0be5046 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -11,6 +11,7 @@ public interface ITeamService Task GetTeamByIdAsync(Guid teamId, CancellationToken token); Task> GetTeamMembersAsync(Guid teamId, CancellationToken token); Task> GetTeamAllAsync(CancellationToken token); + Task> GetTeamForHackathonAsync(Guid hackathonId, CancellationToken token); Task UpdateTeamAsync(UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); //Task> GetTeamsByEventIdAsync(Guid eventId); //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index 655dde9..b59bff5 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -152,11 +152,20 @@ public async Task> GetTeamMembersAsync(Guid teamId, CancellationTok return await teamRepo.GetTeamMembersAsync(teamId, token); } + // Получение команды пользователя для конкретного события + public async Task> GetTeamForHackathonAsync(Guid hackathonId, CancellationToken token) + { + var teams = await teamRepo.GetTeamByHackathonAsync(hackathonId, token); + if (teams is null) return []; + return mapper.ProjectTo(teams.AsQueryable()).ToList(); + } + // Получение списка команд public async Task> GetTeamAllAsync(CancellationToken token) { var teams = await teamRepo.GetTeamsAllAsync(token); + if (teams is null) return []; //return mapper.Map>(teams); return mapper.ProjectTo(teams.AsQueryable()).ToList(); } diff --git a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs index 029a49b..592c281 100644 --- a/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/ITeamRepository.cs @@ -11,6 +11,7 @@ public interface ITeamRepository : IGenericRepository Task GetCaptainIdAsync(Guid teamId, CancellationToken token); Task GetHackathonIdAsync(Guid teamId, CancellationToken token); Task?> GetTeamMembersAsync(Guid teamId, CancellationToken token); + Task?> GetTeamByHackathonAsync(Guid HackathonId, CancellationToken token); Task UpdateTeamAsync(TeamEntity team, CancellationToken token); Task> GetTeamsAllAsync(CancellationToken token); Task GetTeamAsync(Guid teamId, CancellationToken token); From 0b6b348bb28be23c97d347cc9713396323312473 Mon Sep 17 00:00:00 2001 From: wer3454 Date: Tue, 29 Apr 2025 00:09:44 +0300 Subject: [PATCH 43/56] Rework TeamController --- .../Controllers/TeamController.cs | 4 +-- .../Interface/ITeamService.cs | 10 +++---- .../Services/TeamService.cs | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index f36e4f7..43509eb 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -111,7 +111,7 @@ public async Task JoinMember(Guid id, Guid userId, CancellationTok Message = "POST api/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - await teamService.AddUserToTeamAsync(id, userId, userId, token); + await teamService.JoinUserToTeamAsync(id, userId, token); return NoContent(); } @@ -127,7 +127,7 @@ public async Task LeaveMember(Guid id, Guid userId, CancellationTo Message = "DELETE api/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); - await teamService.RemoveUserFromTeamAsync(id, userId, userId, token); + await teamService.LeaveUserFromTeamAsync(id, userId, token); return NoContent(); } diff --git a/MethodologyMain.Application/Interface/ITeamService.cs b/MethodologyMain.Application/Interface/ITeamService.cs index 0be5046..420ac5a 100644 --- a/MethodologyMain.Application/Interface/ITeamService.cs +++ b/MethodologyMain.Application/Interface/ITeamService.cs @@ -1,11 +1,11 @@ using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Model; namespace MethodologyMain.Application.Interface { public interface ITeamService { - Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); Task CreateTeamAsync(CreateTeamDto dto, Guid captainId, CancellationToken token); Task DeleteTeamAsync(Guid teamId, Guid requestingUserId, CancellationToken token, bool isAdmin = false); Task GetTeamByIdAsync(Guid teamId, CancellationToken token); @@ -13,10 +13,10 @@ public interface ITeamService Task> GetTeamAllAsync(CancellationToken token); Task> GetTeamForHackathonAsync(Guid hackathonId, CancellationToken token); Task UpdateTeamAsync(UpdateTeamDto team, Guid requestingUserId, CancellationToken token, bool isAdmin = false); - //Task> GetTeamsByEventIdAsync(Guid eventId); - //Task GetUserTeamForEventAsync(Guid userId, Guid eventId); - //Task IsUserTeamCaptainAsync(Guid teamId, Guid userId); - Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + Task JoinUserToTeamAsync(Guid teamId, Guid userId, CancellationToken token); + Task LeaveUserFromTeamAsync(Guid teamId, Guid userId, CancellationToken token); + //Task AddUserToTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); + //Task RemoveUserFromTeamAsync(Guid teamId, Guid userId, Guid requestingUserId, CancellationToken token); Task TransferCaptainRightsAsync(Guid teamId, Guid newCaptainId, Guid currentCaptainId, CancellationToken token); } } \ No newline at end of file diff --git a/MethodologyMain.Application/Services/TeamService.cs b/MethodologyMain.Application/Services/TeamService.cs index b59bff5..9ed0be8 100644 --- a/MethodologyMain.Application/Services/TeamService.cs +++ b/MethodologyMain.Application/Services/TeamService.cs @@ -125,6 +125,34 @@ CancellationToken token await validation.CheckUserInTeamAsync(userId, teamId, token); await teamRepo.RemoveMemberAsync(userId, teamId, token); } + + // Добавление пользователя в команду + public async Task JoinUserToTeamAsync( + Guid teamId, + Guid userId, + CancellationToken token + ) + { + await validation.CheckTeamExistsAsync(teamId, token); + Guid hackathonId = (Guid)await teamRepo.GetHackathonIdAsync(teamId, token); + await validation.CheckUserNotInTeamAsync(userId, teamId, token); + await validation.CheckUserNotInAnyTeamForHackathonAsync(userId, hackathonId, token); + await teamRepo.AddMemberAsync(userId, teamId, token); + } + + // Удаление пользователя из команды + public async Task LeaveUserFromTeamAsync( + Guid teamId, + Guid userId, + CancellationToken token + ) + { + await validation.CheckTeamExistsAsync(teamId, token); + // Нельзя удалить капитана + await validation.CheckCaptainKick(teamId, userId, token); + await validation.CheckUserInTeamAsync(userId, teamId, token); + await teamRepo.RemoveMemberAsync(userId, teamId, token); + } // Передача прав капитана public async Task TransferCaptainRightsAsync( Guid teamId, From fd840f3a03fe92b0587dd7fe23dabe88f538f16e Mon Sep 17 00:00:00 2001 From: wer3454 Date: Tue, 29 Apr 2025 00:10:14 +0300 Subject: [PATCH 44/56] Add UserController --- .../Controllers/UserController.cs | 56 +++++++++++++++--- MethodologyMain.API/Program.cs | 5 ++ MethodologyMain.Application/DTO/GetUserDto.cs | 2 +- .../Interface/IUserService.cs | 14 ++--- .../Services/UserService.cs | 59 ++++++------------- .../Interfaces/IUserRepository.cs | 4 ++ 6 files changed, 82 insertions(+), 58 deletions(-) diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index c05949a..dbfbf1b 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -14,15 +14,45 @@ namespace MethodologyMain.API.Controllers [Route("api/[controller]")] public class UserController : ControllerBase { - private readonly ITeamService teamService; + private readonly IUserService userService; private readonly IRabbitMqPublisherBase logPublishService; - public UserController(ITeamService teamService, IRabbitMqPublisherBase logPublishService) + public UserController(IUserService userService, IRabbitMqPublisherBase logPublishService) { - this.teamService = teamService; + this.userService = userService; this.logPublishService = logPublishService; } + + [HttpGet] + public async Task>> GetUsers(CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/User was called", + TimeStamp = DateTime.UtcNow + }); + var users = await userService.GetUsersAllAsync(token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(users); + } + + [HttpGet("{id}")] + public async Task>> GetUsersById(Guid id, CancellationToken token) + { + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "GET api/User was called", + TimeStamp = DateTime.UtcNow + }); + var user = await userService.GetUserByIdAsync(id, token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(user); + } [HttpPost] - public async Task> CreateTeam([FromBody] CreateTeamDto dto, CancellationToken token) + public async Task> CreateUser([FromBody] GetUserDto dto, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { @@ -31,14 +61,24 @@ public async Task> CreateTeam([FromBody] CreateTeamDto dto, C Message = "POST api/User was called", TimeStamp = DateTime.UtcNow }); - Guid currentUserId = GetCurrentUserId(); // Получение ID текущего пользователя из токена + var user = await userService.CreateUserAsync(dto, token); //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); - return Ok(); + return Ok(user); } - private Guid GetCurrentUserId() + [HttpPut] + public async Task UpdateUser([FromBody] GetUserDto dto, CancellationToken token) { - return Guid.Parse("1"); + _ = logPublishService.SendEventAsync(new RabbitMqLogPublish + { + ServiceName = "Main service", + LogLevel = LogEventLevel.Information, + Message = "PUT api/User was called", + TimeStamp = DateTime.UtcNow + }); + await userService.UpdateUserAsync(dto, token); + //var team = await teamService.CreateTeamAsync(dto.Name, dto.Description, currentUserId, dto.EventId, token); + return Ok(); } } } diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 2ed637a..52d1d76 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -41,6 +41,10 @@ .ForMember(dto => dto.Members, conf => conf.MapFrom(t => t.Members.Select(s => s.User.UserName).ToList())) .ForMember(dto => dto.Tags, conf => conf.MapFrom(t => t.Tags.Select(s => s.Tag.TagName).ToList())) .ForMember(dto => dto.CreatedAt, conf => conf.MapFrom(t => t.TeamCreatedAt)); + cfg.CreateMap() + .ForMember(dto => dto.Tags, conf => conf.MapFrom(t => t.Tags.Select(s => s.Tag.TagName).ToList())) + .ForMember(dto => dto.Name, conf => conf.MapFrom(t => t.UserName)) + .ForMember(dto => dto.Bio, conf => conf.MapFrom(t => t.Education)); cfg.AllowNullCollections = true; cfg.AddGlobalIgnore("Item"); @@ -55,6 +59,7 @@ builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddAutoMapper(typeof(TeamProfile).Assembly, typeof(TeamInfoDto).Assembly); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/MethodologyMain.Application/DTO/GetUserDto.cs b/MethodologyMain.Application/DTO/GetUserDto.cs index 667504d..50cb669 100644 --- a/MethodologyMain.Application/DTO/GetUserDto.cs +++ b/MethodologyMain.Application/DTO/GetUserDto.cs @@ -14,6 +14,6 @@ public class GetUserDto public string Location { get; set; } = string.Empty; public string Github { get; set; } = string.Empty; public string Website { get; set; } = string.Empty; - public List Skills { get; set; } = null!; + public string Skills { get; set; } = string.Empty; } } diff --git a/MethodologyMain.Application/Interface/IUserService.cs b/MethodologyMain.Application/Interface/IUserService.cs index 842b11e..84845c6 100644 --- a/MethodologyMain.Application/Interface/IUserService.cs +++ b/MethodologyMain.Application/Interface/IUserService.cs @@ -1,18 +1,14 @@ using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; -using MethodologyMain.Logic.Models; namespace MethodologyMain.Application.Interface { public interface IUserService { - Task CreateUserAsync( - string UserName, - string description, - Guid captainId, - DateTime BirthDate, - CancellationToken token - ); - + Task CreateUserAsync(GetUserDto dto, CancellationToken token); + Task DeleteUserAsync(Guid userId, CancellationToken token); + Task GetUserByIdAsync(Guid userId, CancellationToken token); + Task> GetUsersAllAsync(CancellationToken token); + Task UpdateUserAsync(GetUserDto dto, CancellationToken token); } } diff --git a/MethodologyMain.Application/Services/UserService.cs b/MethodologyMain.Application/Services/UserService.cs index c28571f..2386c8a 100644 --- a/MethodologyMain.Application/Services/UserService.cs +++ b/MethodologyMain.Application/Services/UserService.cs @@ -1,11 +1,12 @@ using AutoMapper; +using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; -using MethodologyMain.Logic.Models; +using MethodologyMain.Application.Interface; using MethodologyMain.Persistence.Interfaces; namespace MethodologyMain.Application.Services { - class UserService + public class UserService : IUserService { private readonly IUserRepository userRepo; private readonly IMapper mapper; @@ -16,64 +17,42 @@ public UserService(IUserRepository userRepo, IMapper mapper) } // Создание нового пользователя - public async Task CreateUserAsync( - string UserName, - string description, - Guid captainId, - DateTime BirthDate, - CancellationToken token - ) + public async Task CreateUserAsync(GetUserDto dto, CancellationToken token) { - // Создание пользователя - var user = new UserMainEntity - { - Id = Guid.NewGuid(), - UserName = UserName, - BirthDate = BirthDate - }; + var user = mapper.Map(dto); await userRepo.AddAsync(user, token); - return user; + return dto; } - - // Удаление команды (только капитаном или администратором) - public async Task DeleteUserAsync( - Guid userId, - Guid requestingUserId, - CancellationToken token, - bool isAdmin = false - ) + public async Task DeleteUserAsync(Guid userId, CancellationToken token) { - throw new NotImplementedException(); + await userRepo.RemoveAsync(userId, token); // await validation.CheckTeamExistsAsync(teamId, token); // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); // await userRepo.RemoveAsync(teamId, token); } - public async Task UpdateUserAsync( - Guid userId, - Guid requestingUserId, - CancellationToken token, - bool isAdmin = false - ) + public async Task UpdateUserAsync(GetUserDto dto, CancellationToken token) { - throw new NotImplementedException(); + var user = mapper.Map(dto); + await userRepo.UpdateAsync(user, token); // await validation.CheckTeamExistsAsync(teamId, token); // await validation.CheckUserIsCaptainOrAdminAsync(teamId, requestingUserId, isAdmin, token); // await userRepo.RemoveAsync(teamId, token); } - // Получение информации о команде по ID - public async Task GetUserByIdAsync(Guid userId, CancellationToken token) + // Получение информации о пользователе по ID + public async Task GetUserByIdAsync(Guid userId, CancellationToken token) { // await validation.CheckTeamExistsAsync(teamId, token); - return await userRepo.GetByIdAsync(userId, token); + var user = await userRepo.GetByIdAsync(userId, token); + return mapper.Map(user); } - // Получение списка команд - public async Task> GetUsersAllAsync(CancellationToken token) + // Получение списка пользователей + public async Task> GetUsersAllAsync(CancellationToken token) { - var teams = await userRepo.GetAllAsync(token); - return mapper.Map>(teams); + var users = await userRepo.GetAllAsync(token); + return mapper.Map>(users); } } } diff --git a/MethodologyMain.Persistence/Interfaces/IUserRepository.cs b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs index a53ee09..0759910 100644 --- a/MethodologyMain.Persistence/Interfaces/IUserRepository.cs +++ b/MethodologyMain.Persistence/Interfaces/IUserRepository.cs @@ -9,5 +9,9 @@ namespace MethodologyMain.Persistence.Interfaces { public interface IUserRepository : IGenericRepository { + Task CheckUserTeamInHackAsync(Guid userId, Guid hackathonId, CancellationToken token); + Task UpdateAsync(UserMainEntity user, CancellationToken token); + Task RemoveAsync(Guid userId, CancellationToken token); + } } From e7260c69e6f4e7a02f5b6fbc5863b58287162d04 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Tue, 29 Apr 2025 16:48:57 +0300 Subject: [PATCH 45/56] Minor fixes Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/TeamController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 6265947..1ded93a 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -1,5 +1,4 @@ using MethodologyMain.Application.DTO; -using MethodTeams.Models; //using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; //using System.Security.Claims; From 03474fc6a482f5d00c1d1b8ffae2313616390c24 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Tue, 29 Apr 2025 16:49:19 +0300 Subject: [PATCH 46/56] Change controller routing path Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/UserController.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index dbfbf1b..80f6099 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -1,8 +1,5 @@ using MethodologyMain.Application.DTO; -using MethodTeams.Models; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using System.Security.Claims; using MethodologyMain.Application.Interface; using AuthMetodology.Infrastructure.Models; using Serilog.Events; @@ -11,7 +8,7 @@ namespace MethodologyMain.API.Controllers { [ApiController] - [Route("api/[controller]")] + [Route("api/main/[controller]")] public class UserController : ControllerBase { private readonly IUserService userService; From c592e57ea03bb733f52ac6e29e50bb0f65fdf134 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Tue, 29 Apr 2025 16:49:57 +0300 Subject: [PATCH 47/56] Add new folders to ignore --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9491a2f..a515779 100644 --- a/.gitignore +++ b/.gitignore @@ -360,4 +360,8 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd + +docker-compose/ + +postgres-data/ \ No newline at end of file From 13d61bca05b59efc7e76f705ffd1d5d5600be038 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Tue, 29 Apr 2025 16:50:20 +0300 Subject: [PATCH 48/56] Minor fixes --- .../Listeners/RabbitMqUserRegisterListener.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs index 825be6d..5f0d9df 100644 --- a/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs +++ b/MethodologyMain.Infrastructure/Listeners/RabbitMqUserRegisterListener.cs @@ -43,8 +43,7 @@ await context.AddAsync(new UserMainEntity UserName = data.UserName, Email = data.Email, }); - } - + } } } } From b3c882abb014c36a82e91e598ed9ebd89e8c17c8 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Tue, 29 Apr 2025 16:50:36 +0300 Subject: [PATCH 49/56] Merge stuff --- .../Migrations/MyDbContextModelSnapshot.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs index b0106d7..a11516b 100644 --- a/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs +++ b/MethodologyMain.Persistence/Migrations/MyDbContextModelSnapshot.cs @@ -435,6 +435,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Tags"); b.Navigation("Teams"); + + b.Navigation("Tracks"); }); modelBuilder.Entity("MethodologyMain.Logic.Entities.OrganizationEntity", b => From f18f9f4f804fff32fcef826b5bbe78eab63fbc18 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:10:38 +0300 Subject: [PATCH 50/56] Fix message content in log props Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/TeamController.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index 1ded93a..d00084a 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -28,7 +28,7 @@ public async Task GetDummyData(CancellationToken cancellationToke { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team/dummy-data was called", + Message = "POST api/main/Team/dummy-data was called", TimeStamp = DateTime.UtcNow }, cancellationToken); string data = "Dataaa"; @@ -43,7 +43,7 @@ public async Task>> GetTeamsAll(CancellationToken { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/Team was called", + Message = "GET api/main/Team was called", TimeStamp = DateTime.UtcNow }, token); var teams = await teamService.GetTeamAllAsync(token); @@ -58,7 +58,7 @@ public async Task>> GetTeamsForHackathon(Guid hack { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/Team/hackathon/id was called", + Message = "GET api/main/Team/hackathon/id was called", TimeStamp = DateTime.UtcNow }, token); var teams = await teamService.GetTeamForHackathonAsync(hackId, token); @@ -74,7 +74,7 @@ public async Task> CreateTeam([FromBody] CreateTeamD { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team was called", + Message = "POST api/main/Team was called", TimeStamp = DateTime.UtcNow }, token); // Получение ID текущего пользователя из токена @@ -90,7 +90,7 @@ public async Task> GetTeamById(Guid id, CancellationTok { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/Team/id was called", + Message = "GET api/main/Team/id was called", TimeStamp = DateTime.UtcNow }, token); var team = await teamService.GetTeamByIdAsync(id, token); @@ -106,7 +106,7 @@ public async Task JoinMember(Guid id, Guid userId, CancellationTok { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/Team/id/users/userId was called", + Message = "POST api/main/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); await teamService.JoinUserToTeamAsync(id, userId, token); @@ -122,7 +122,7 @@ public async Task LeaveMember(Guid id, Guid userId, CancellationTo { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "DELETE api/Team/id/users/userId was called", + Message = "DELETE api/main/Team/id/users/userId was called", TimeStamp = DateTime.UtcNow }, token); await teamService.LeaveUserFromTeamAsync(id, userId, token); From 29072f723bdabd7af2a5445c6f4a7c74637e496f Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:12:40 +0300 Subject: [PATCH 51/56] Specify route attribute for id in GetUserById method and fix log message properties Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/UserController.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index 80f6099..e697a28 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -26,7 +26,7 @@ public async Task>> GetUsers(CancellationToken tok { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/User was called", + Message = "GET api/main/User was called", TimeStamp = DateTime.UtcNow }); var users = await userService.GetUsersAllAsync(token); @@ -35,13 +35,13 @@ public async Task>> GetUsers(CancellationToken tok } [HttpGet("{id}")] - public async Task>> GetUsersById(Guid id, CancellationToken token) + public async Task> GetUsersById([FromRoute] Guid id, CancellationToken token) { _ = logPublishService.SendEventAsync(new RabbitMqLogPublish { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "GET api/User was called", + Message = "GET api/main/User was called", TimeStamp = DateTime.UtcNow }); var user = await userService.GetUserByIdAsync(id, token); @@ -55,7 +55,7 @@ public async Task> CreateUser([FromBody] GetUserDto dto { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "POST api/User was called", + Message = "POST api/main/User was called", TimeStamp = DateTime.UtcNow }); var user = await userService.CreateUserAsync(dto, token); @@ -70,7 +70,7 @@ public async Task UpdateUser([FromBody] GetUserDto dto, Cancellati { ServiceName = "Main service", LogLevel = LogEventLevel.Information, - Message = "PUT api/User was called", + Message = "PUT api/main/User was called", TimeStamp = DateTime.UtcNow }); await userService.UpdateUserAsync(dto, token); From 9f1a9420037390af233127e7698d2b87513d5624 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:13:33 +0300 Subject: [PATCH 52/56] Add new config to specify cross origin resource sharing Signed-off-by: BelugaChan --- MethodologyMain.API/Extensions/AuthExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MethodologyMain.API/Extensions/AuthExtensions.cs b/MethodologyMain.API/Extensions/AuthExtensions.cs index c65b833..ff86409 100644 --- a/MethodologyMain.API/Extensions/AuthExtensions.cs +++ b/MethodologyMain.API/Extensions/AuthExtensions.cs @@ -36,6 +36,17 @@ public static void AddApiAuthentication( } }; }); + services.AddCors(options => + { + options.AddPolicy("AllowFrontend", builder => + { + builder.WithOrigins("http://localhost:8083") + .AllowCredentials() + .AllowAnyHeader() + .AllowAnyMethod() + .WithExposedHeaders("Set-Cookie"); + }); + }); services.AddAuthorizationBuilder() //.AddPolicy("AdminOnly", policy => policy.RequireRole(nameof(UserRole.Admin))) .AddPolicy("BearerOnly", policy => { policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); From 779e36a051554aaa7d7b3fbee1d11c372f7be31e Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:14:20 +0300 Subject: [PATCH 53/56] Add config for console logging using serilog Signed-off-by: BelugaChan --- MethodologyMain.API/Program.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MethodologyMain.API/Program.cs b/MethodologyMain.API/Program.cs index 50017de..b42589a 100644 --- a/MethodologyMain.API/Program.cs +++ b/MethodologyMain.API/Program.cs @@ -21,9 +21,17 @@ using MethodologyMain.Infrastructure.Listeners; using MethodologyMain.Application.DTO; using MethodologyMain.Logic.Entities; +using Serilog; var builder = WebApplication.CreateBuilder(args); +var logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateLogger(); + +builder.Logging.ClearProviders(); +builder.Logging.AddSerilog(logger); + builder.Services.AddControllers(); builder.Services.AddControllers() .AddJsonOptions(options => @@ -85,6 +93,7 @@ app.UseHttpsRedirection(); +app.UseCors("AllowFrontend"); app.UseAuthorization(); app.UseAuthentication(); From daac19b52bf45d09b3df4c6b1b63d65036783bbc Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:14:48 +0300 Subject: [PATCH 54/56] Add new nuget packages (serilog) Signed-off-by: BelugaChan --- MethodologyMain.API/MethodologyMain.API.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MethodologyMain.API/MethodologyMain.API.csproj b/MethodologyMain.API/MethodologyMain.API.csproj index f777033..1fb77ba 100644 --- a/MethodologyMain.API/MethodologyMain.API.csproj +++ b/MethodologyMain.API/MethodologyMain.API.csproj @@ -20,6 +20,8 @@ + + From 7bfe7b7c3db6794b660b7240110b1c535927dc92 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:15:42 +0300 Subject: [PATCH 55/56] New Folder section in ItemGroup Signed-off-by: BelugaChan --- .../MethodologyMain.Persistence.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj index 0dbfb18..c06086d 100644 --- a/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj +++ b/MethodologyMain.Persistence/MethodologyMain.Persistence.csproj @@ -11,10 +11,6 @@ - - - - @@ -24,4 +20,8 @@ + + + + From 0b0534324333f64b8a71881f946401fc10dc38f1 Mon Sep 17 00:00:00 2001 From: BelugaChan Date: Wed, 30 Apr 2025 15:25:01 +0300 Subject: [PATCH 56/56] Add an attribute to enable cors Signed-off-by: BelugaChan --- MethodologyMain.API/Controllers/TeamController.cs | 2 ++ MethodologyMain.API/Controllers/UserController.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/MethodologyMain.API/Controllers/TeamController.cs b/MethodologyMain.API/Controllers/TeamController.cs index d00084a..9a9a078 100644 --- a/MethodologyMain.API/Controllers/TeamController.cs +++ b/MethodologyMain.API/Controllers/TeamController.cs @@ -6,9 +6,11 @@ using AuthMetodology.Infrastructure.Models; using Serilog.Events; using RabbitMqPublisher.Interface; +using Microsoft.AspNetCore.Cors; namespace MethodologyMain.API.Controllers { [ApiController] + [EnableCors("AllowFrontend")] [Route("api/main/[controller]")] public class TeamController : ControllerBase { diff --git a/MethodologyMain.API/Controllers/UserController.cs b/MethodologyMain.API/Controllers/UserController.cs index e697a28..7644283 100644 --- a/MethodologyMain.API/Controllers/UserController.cs +++ b/MethodologyMain.API/Controllers/UserController.cs @@ -4,10 +4,12 @@ using AuthMetodology.Infrastructure.Models; using Serilog.Events; using RabbitMqPublisher.Interface; +using Microsoft.AspNetCore.Cors; namespace MethodologyMain.API.Controllers { [ApiController] + [EnableCors("AllowFrontend")] [Route("api/main/[controller]")] public class UserController : ControllerBase {