From dbcdfac698eb2ff0fff51529c06a4b143eebc833 Mon Sep 17 00:00:00 2001 From: shept Date: Sat, 19 Apr 2025 00:16:07 +0500 Subject: [PATCH] added CreatedBy to surveys --- .../Controllers/AuthController.cs | 8 +- .../Controllers/SurveyController.cs | 9 + SurveyBackend/SurveyBackend.API/Program.cs | 28 +- .../Data/ApplicationDbContext.cs | 24 +- ...190738_Add CreatedBy to Survey.Designer.cs | 334 ++++++++++++++++++ .../20250418190738_Add CreatedBy to Survey.cs | 49 +++ .../ApplicationDbContextModelSnapshot.cs | 13 + 7 files changed, 443 insertions(+), 22 deletions(-) create mode 100644 SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.Designer.cs create mode 100644 SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.cs diff --git a/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs b/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs index 882c94b..06bfddc 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/AuthController.cs @@ -1,7 +1,8 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using SurveyBackend.Core.Services; using SurveyBackend.DTOs; using SurveyBackend.Mappers.UserDTOs; +using IAuthorizationService = SurveyBackend.Core.Services.IAuthorizationService; namespace SurveyBackend.Controllers; @@ -16,6 +17,7 @@ public class AuthController : ControllerBase _authorizationService = authorizationService; } + [AllowAnonymous] [HttpPost("login")] public async Task LogIn([FromBody] UserLoginDto loginData) { @@ -23,10 +25,12 @@ public class AuthController : ControllerBase return Ok(new { token = token }); } + [AllowAnonymous] [HttpPost("register")] public async Task Register([FromBody] UserRegistrationDto registerData) { - var token = await _authorizationService.RegisterUser(UserRegistrationMapper.UserRegistrationToModel(registerData)); + var token = await _authorizationService.RegisterUser( + UserRegistrationMapper.UserRegistrationToModel(registerData)); return Ok(new { token = token }); } } \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs b/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs index 5a96f0b..c98acfe 100644 --- a/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs +++ b/SurveyBackend/SurveyBackend.API/Controllers/SurveyController.cs @@ -1,3 +1,5 @@ +using System.Security.Claims; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SurveyBackend.DTOs.Survey; using SurveyLib.Core.Models; @@ -17,6 +19,7 @@ public class SurveyController : ControllerBase _surveyService = surveyService; } + [AllowAnonymous] [HttpGet] public async Task Get() { @@ -24,6 +27,7 @@ public class SurveyController : ControllerBase return Ok(result); } + [AllowAnonymous] [HttpGet("{id}")] public async Task Get(int id) { @@ -31,18 +35,23 @@ public class SurveyController : ControllerBase return result is not null ? Ok(result) : NotFound(); } + [Authorize] [HttpPost] public async Task Post([FromBody] CreateSurveyDTO dto) { + var userId = Convert.ToInt32(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value); + var survey = new Survey { Title = dto.Title, Description = dto.Description, + CreatedBy = userId, }; await _surveyService.AddSurveyAsync(survey); return Ok(); } + [Authorize] [HttpDelete("{id}")] public async Task Delete(int id) { diff --git a/SurveyBackend/SurveyBackend.API/Program.cs b/SurveyBackend/SurveyBackend.API/Program.cs index 6a2bf3f..eeea7af 100644 --- a/SurveyBackend/SurveyBackend.API/Program.cs +++ b/SurveyBackend/SurveyBackend.API/Program.cs @@ -2,6 +2,7 @@ using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using SurveyBackend.Core.Repositories; using SurveyBackend.Core.Services; using SurveyBackend.Infrastructure; @@ -62,7 +63,32 @@ public class Program builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(); + builder.Services.AddSwaggerGen(c => + { + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Scheme = "bearer", + BearerFormat = "JWT", + In = ParameterLocation.Header, + Description = "JWT Authorization header using the Bearer scheme.", + Name = "Authorization", + Type = SecuritySchemeType.ApiKey + }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = JwtBearerDefaults.AuthenticationScheme + } + }, + Array.Empty() + } + }); + }); var app = builder.Build(); diff --git a/SurveyBackend/SurveyBackend.Infrastructure/Data/ApplicationDbContext.cs b/SurveyBackend/SurveyBackend.Infrastructure/Data/ApplicationDbContext.cs index 66a0468..3a0cda7 100644 --- a/SurveyBackend/SurveyBackend.Infrastructure/Data/ApplicationDbContext.cs +++ b/SurveyBackend/SurveyBackend.Infrastructure/Data/ApplicationDbContext.cs @@ -13,30 +13,16 @@ public class ApplicationDbContext : SurveyDbContext public ApplicationDbContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) { - // Вызов конфигурации базового контекста для моделей библиотеки base.OnModelCreating(modelBuilder); - // Здесь можно описывать конфигурацию дополнительных сущностей и связи между моделями библиотеки и моделями приложения. - // Например, если Survey должен иметь связь с User (скажем, владелец опроса): - - // Допустим, Survey не имеет в исходной модели свойства UserId. - // Можно использовать теневой ключ, или если ты готов расширить модель Survey в бэкенде. - // Пример с теневым ключом: - // modelBuilder.Entity() - // .HasOne() // тип связи: один пользователь - // .WithMany() // например, пользователь может владеть несколькими опросами - // .HasForeignKey("OwnerId"); // теневой ключ, который не прописан в модели Survey - - // Или, если расширить Survey: - // public int? OwnerId { get; set; } - // modelBuilder.Entity() - // .HasOne() - // .WithMany(u => u.Surveys) - // .HasForeignKey(s => s.OwnerId); + modelBuilder.Entity() + .HasOne() + .WithMany() + .HasForeignKey(s => s.CreatedBy) + .OnDelete(DeleteBehavior.SetNull); } } \ No newline at end of file diff --git a/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.Designer.cs b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.Designer.cs new file mode 100644 index 0000000..e7f3c8e --- /dev/null +++ b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.Designer.cs @@ -0,0 +1,334 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SurveyBackend.Infrastructure.Data; + +#nullable disable + +namespace SurveyBackend.Infrastructure.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20250418190738_Add CreatedBy to Survey")] + partial class AddCreatedBytoSurvey + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.15"); + + modelBuilder.Entity("GroupUser", b => + { + b.Property("GroupsId") + .HasColumnType("INTEGER"); + + b.Property("UsersId") + .HasColumnType("INTEGER"); + + b.HasKey("GroupsId", "UsersId"); + + b.HasIndex("UsersId"); + + b.ToTable("GroupUser"); + }); + + modelBuilder.Entity("SurveyBackend.Core.Models.Group", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("SurveyBackend.Core.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Email") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Answer", b => + { + b.Property("CompletionId") + .HasColumnType("INTEGER"); + + b.Property("QuestionId") + .HasColumnType("INTEGER"); + + b.Property("AnswerText") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("CompletionId", "QuestionId"); + + b.HasIndex("QuestionId"); + + b.ToTable("Answers"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.AnswerVariant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MultipleAnswerQuestionId") + .HasColumnType("INTEGER"); + + b.Property("QuestionId") + .HasColumnType("INTEGER"); + + b.Property("SingleAnswerQuestionId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MultipleAnswerQuestionId"); + + b.HasIndex("QuestionId"); + + b.HasIndex("SingleAnswerQuestionId"); + + b.ToTable("AnswerVariant"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Completion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("FinishedAt") + .HasColumnType("TEXT"); + + b.Property("SurveyId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SurveyId"); + + b.ToTable("Completions"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionBase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(34) + .HasColumnType("TEXT"); + + b.Property("SurveyId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SurveyId"); + + b.ToTable("Questions"); + + b.HasDiscriminator().HasValue("QuestionBase"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Survey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Surveys"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionVariants.MultipleAnswerQuestion", b => + { + b.HasBaseType("SurveyLib.Core.Models.QuestionBase"); + + b.HasDiscriminator().HasValue("MultipleAnswerQuestion"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionVariants.SingleAnswerQuestion", b => + { + b.HasBaseType("SurveyLib.Core.Models.QuestionBase"); + + b.HasDiscriminator().HasValue("SingleAnswerQuestion"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionVariants.TextQuestion", b => + { + b.HasBaseType("SurveyLib.Core.Models.QuestionBase"); + + b.HasDiscriminator().HasValue("TextQuestion"); + }); + + modelBuilder.Entity("GroupUser", b => + { + b.HasOne("SurveyBackend.Core.Models.Group", null) + .WithMany() + .HasForeignKey("GroupsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SurveyBackend.Core.Models.User", null) + .WithMany() + .HasForeignKey("UsersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Answer", b => + { + b.HasOne("SurveyLib.Core.Models.Completion", "Completion") + .WithMany("Answers") + .HasForeignKey("CompletionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SurveyLib.Core.Models.QuestionBase", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Completion"); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.AnswerVariant", b => + { + b.HasOne("SurveyLib.Core.Models.QuestionVariants.MultipleAnswerQuestion", null) + .WithMany("AnswerVariants") + .HasForeignKey("MultipleAnswerQuestionId"); + + b.HasOne("SurveyLib.Core.Models.QuestionBase", "Question") + .WithMany() + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SurveyLib.Core.Models.QuestionVariants.SingleAnswerQuestion", null) + .WithMany("AnswerVariants") + .HasForeignKey("SingleAnswerQuestionId"); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Completion", b => + { + b.HasOne("SurveyLib.Core.Models.Survey", "Survey") + .WithMany("Completions") + .HasForeignKey("SurveyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Survey"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionBase", b => + { + b.HasOne("SurveyLib.Core.Models.Survey", "Survey") + .WithMany("Questions") + .HasForeignKey("SurveyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Survey"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Survey", b => + { + b.HasOne("SurveyBackend.Core.Models.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Completion", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionBase", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.Survey", b => + { + b.Navigation("Completions"); + + b.Navigation("Questions"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionVariants.MultipleAnswerQuestion", b => + { + b.Navigation("AnswerVariants"); + }); + + modelBuilder.Entity("SurveyLib.Core.Models.QuestionVariants.SingleAnswerQuestion", b => + { + b.Navigation("AnswerVariants"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.cs b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.cs new file mode 100644 index 0000000..3debfa9 --- /dev/null +++ b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418190738_Add CreatedBy to Survey.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SurveyBackend.Infrastructure.Data.Migrations +{ + /// + public partial class AddCreatedBytoSurvey : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedBy", + table: "Surveys", + type: "INTEGER", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Surveys_CreatedBy", + table: "Surveys", + column: "CreatedBy"); + + migrationBuilder.AddForeignKey( + name: "FK_Surveys_Users_CreatedBy", + table: "Surveys", + column: "CreatedBy", + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Surveys_Users_CreatedBy", + table: "Surveys"); + + migrationBuilder.DropIndex( + name: "IX_Surveys_CreatedBy", + table: "Surveys"); + + migrationBuilder.DropColumn( + name: "CreatedBy", + table: "Surveys"); + } + } +} diff --git a/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index db4d61e..8441af9 100644 --- a/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -177,6 +177,9 @@ namespace SurveyBackend.Infrastructure.Data.Migrations .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); + b.Property("CreatedBy") + .HasColumnType("INTEGER"); + b.Property("Description") .IsRequired() .HasColumnType("TEXT"); @@ -187,6 +190,8 @@ namespace SurveyBackend.Infrastructure.Data.Migrations b.HasKey("Id"); + b.HasIndex("CreatedBy"); + b.ToTable("Surveys"); }); @@ -286,6 +291,14 @@ namespace SurveyBackend.Infrastructure.Data.Migrations b.Navigation("Survey"); }); + modelBuilder.Entity("SurveyLib.Core.Models.Survey", b => + { + b.HasOne("SurveyBackend.Core.Models.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.SetNull); + }); + modelBuilder.Entity("SurveyLib.Core.Models.Completion", b => { b.Navigation("Answers");