Merge branch 'unstable' into 'main'
Swagger-docs Update! See merge request internship-2025/survey-webapp/survey-webapp!10
This commit is contained in:
commit
64a10ac32d
20 changed files with 287 additions and 18 deletions
|
|
@ -1,19 +1,31 @@
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using SurveyBackend.Core.Contexts;
|
using SurveyBackend.Core.Contexts;
|
||||||
|
using SurveyBackend.Services.Exceptions;
|
||||||
|
|
||||||
namespace SurveyBackend.Contexts;
|
namespace SurveyBackend.Contexts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Упрощает получение UserId из JWT-токена
|
||||||
|
/// </summary>
|
||||||
public class UserContext : IUserContext
|
public class UserContext : IUserContext
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавьте HttpContextAccessor в DI и будет счастье
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContextAccessor"></param>
|
||||||
public UserContext(IHttpContextAccessor httpContextAccessor)
|
public UserContext(IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Возвращает UserId из токена, при отсуствии кидает Unauthorized
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="UnauthorizedAccessException"></exception>
|
||||||
public int UserId =>
|
public int UserId =>
|
||||||
int.Parse(
|
int.Parse(
|
||||||
_httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)
|
_httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)
|
||||||
?.Value ?? throw new UnauthorizedAccessException());
|
?.Value ?? throw new UnauthorizedException("Where's your token mister"));
|
||||||
}
|
}
|
||||||
|
|
@ -6,17 +6,32 @@ using IAuthorizationService = SurveyBackend.Core.Services.IAuthorizationService;
|
||||||
|
|
||||||
namespace SurveyBackend.Controllers;
|
namespace SurveyBackend.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Контроллер для всего связанного с авторизацией пользователей
|
||||||
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/auth")]
|
[Route("api/auth")]
|
||||||
public class AuthController : ControllerBase
|
public class AuthController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IAuthorizationService _authorizationService;
|
private readonly IAuthorizationService _authorizationService;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Нет ну вы прикалываетесь что ли мне ща каждый контроллер описывать?
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authorizationService"></param>
|
||||||
public AuthController(IAuthorizationService authorizationService)
|
public AuthController(IAuthorizationService authorizationService)
|
||||||
{
|
{
|
||||||
_authorizationService = authorizationService;
|
_authorizationService = authorizationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Авторизация
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Принимает на вход email и password. При отсутствии такого email вернет 404, при неправильном пароле 401, при успехе 200 и валидный токен</remarks>
|
||||||
|
/// <param name="loginData"></param>
|
||||||
|
/// <response code="200">Success: Возвращает токен</response>
|
||||||
|
/// <response code="401">Unauthorized: Неправильный пароль</response>
|
||||||
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
|
@ -27,6 +42,12 @@ public class AuthController : ControllerBase
|
||||||
return Ok(new { token = token });
|
return Ok(new { token = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Регистрация
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Принимает на вход кучу всяких полей, потом разберемся</remarks>
|
||||||
|
/// <param name="registerData"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,25 @@ using SurveyLib.Core.Services;
|
||||||
|
|
||||||
namespace SurveyBackend.Controllers;
|
namespace SurveyBackend.Controllers;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/surveys/{surveyId}/questions")]
|
[Route("api/surveys/{surveyId}/questions")]
|
||||||
public class QuestionController : ControllerBase
|
public class QuestionController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IQuestionService _questionService;
|
private readonly IQuestionService _questionService;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public QuestionController(IQuestionService questionService, IUserContext userContext)
|
public QuestionController(IQuestionService questionService, IUserContext userContext)
|
||||||
{
|
{
|
||||||
_questionService = questionService;
|
_questionService = questionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Возвращает список вопросов из опроса по его ID
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Получение вопросов по ID опроса. В случае отсутствия опроса с таким идентификатором выкидывает 404</remarks>
|
||||||
|
/// <param name="surveyId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|
@ -29,6 +37,13 @@ public class QuestionController : ControllerBase
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавить вопрос к опросу
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>К опросу с указанным ID добавляет вопрос. Если я правильно написал, при отсутствии такого опроса кинет 404</remarks>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <param name="surveyId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ using SurveyLib.Core.Services;
|
||||||
|
|
||||||
namespace SurveyBackend.Controllers;
|
namespace SurveyBackend.Controllers;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/surveys")]
|
[Route("api/surveys")]
|
||||||
public class SurveyController : ControllerBase
|
public class SurveyController : ControllerBase
|
||||||
|
|
@ -17,12 +18,18 @@ public class SurveyController : ControllerBase
|
||||||
private readonly ISurveyService _surveyService;
|
private readonly ISurveyService _surveyService;
|
||||||
private readonly IUserContext _userContext;
|
private readonly IUserContext _userContext;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public SurveyController(ISurveyService surveyService, IUserContext userContext)
|
public SurveyController(ISurveyService surveyService, IUserContext userContext)
|
||||||
{
|
{
|
||||||
_surveyService = surveyService;
|
_surveyService = surveyService;
|
||||||
_userContext = userContext;
|
_userContext = userContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить ВСЕ опросы
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Возвращает массив вообще всех опросов</remarks>
|
||||||
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(List<OutputSurveyDto>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<OutputSurveyDto>), StatusCodes.Status200OK)]
|
||||||
|
|
@ -33,6 +40,12 @@ public class SurveyController : ControllerBase
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить опрос по ID
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>А что тут говорить то</remarks>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|
@ -44,6 +57,12 @@ public class SurveyController : ControllerBase
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавить новый опрос
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks></remarks>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||||
|
|
@ -56,6 +75,12 @@ public class SurveyController : ControllerBase
|
||||||
return Created();
|
return Created();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Удалить опрос по ID
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Опрос должен быть создан тобой чтоб его удалить</remarks>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|
@ -67,6 +92,11 @@ public class SurveyController : ControllerBase
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить МОИ опроса
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Возвращает только опросы созданные нынешним юзером</remarks>
|
||||||
|
/// <returns></returns>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpGet("my")]
|
[HttpGet("my")]
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ using SurveyLib.Core.Services;
|
||||||
|
|
||||||
namespace SurveyBackend.Controllers;
|
namespace SurveyBackend.Controllers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Удалим когда-нибудь
|
||||||
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/test")]
|
[Route("api/test")]
|
||||||
public class TestController : ControllerBase
|
public class TestController : ControllerBase
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,21 @@
|
||||||
namespace SurveyBackend.DTOs.Question;
|
namespace SurveyBackend.DTOs.Question;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Схема для создания нового Question
|
||||||
|
/// </summary>
|
||||||
public class CreateQuestionDto
|
public class CreateQuestionDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Название вопроса
|
||||||
|
/// </summary>
|
||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Тип вопроса
|
||||||
|
/// </summary>
|
||||||
public required string QuestionType { get; set; }
|
public required string QuestionType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Варианты ответа (только если вопрос с выбором)
|
||||||
|
/// </summary>
|
||||||
public List<string>? AnswerVariants { get; set; }
|
public List<string>? AnswerVariants { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,20 @@
|
||||||
namespace SurveyBackend.DTOs.Question;
|
namespace SurveyBackend.DTOs.Question;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Выходная схема вариантов ответа
|
||||||
|
/// </summary>
|
||||||
public class OutputAnswerVariantDto
|
public class OutputAnswerVariantDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ID варианта ответа
|
||||||
|
/// </summary>
|
||||||
public required int Id { get; set; }
|
public required int Id { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// ID родительского вопроса
|
||||||
|
/// </summary>
|
||||||
public required int QuestionId { get; set; }
|
public required int QuestionId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Текст варианта ответа
|
||||||
|
/// </summary>
|
||||||
public required string Text { get; set; }
|
public required string Text { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,32 @@
|
||||||
namespace SurveyBackend.DTOs.Question;
|
namespace SurveyBackend.DTOs.Question;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Выходнпя схема вопроса
|
||||||
|
/// </summary>
|
||||||
public class OutputQuestionDto
|
public class OutputQuestionDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ID вопроса
|
||||||
|
/// </summary>
|
||||||
public required int Id { get; set; }
|
public required int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID родительского опроса
|
||||||
|
/// </summary>
|
||||||
public required int SurveyId { get; set; }
|
public required int SurveyId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Заголовок вопроса
|
||||||
|
/// </summary>
|
||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Тип вопроса
|
||||||
|
/// </summary>
|
||||||
public required string QuestionType { get; set; }
|
public required string QuestionType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Варианты ответа
|
||||||
|
/// </summary>
|
||||||
public List<OutputAnswerVariantDto>? AnswerVariants { get; set; }
|
public List<OutputAnswerVariantDto>? AnswerVariants { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
namespace SurveyBackend.DTOs.Survey;
|
namespace SurveyBackend.DTOs.Survey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Схема для создания нового опроса
|
||||||
|
/// </summary>
|
||||||
public class CreateSurveyDto
|
public class CreateSurveyDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Название опроса
|
||||||
|
/// </summary>
|
||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Опциональное описание опроса
|
||||||
|
/// </summary>
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,24 @@
|
||||||
namespace SurveyBackend.DTOs.Survey;
|
namespace SurveyBackend.DTOs.Survey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Выходная схема опроса
|
||||||
|
/// </summary>
|
||||||
public class OutputSurveyDto
|
public class OutputSurveyDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ID опроса
|
||||||
|
/// </summary>
|
||||||
public required int Id { get; set; }
|
public required int Id { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Название опроса
|
||||||
|
/// </summary>
|
||||||
public required string Title { get; set; }
|
public required string Title { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Описание опроса
|
||||||
|
/// </summary>
|
||||||
public required string Description { get; set; }
|
public required string Description { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Создатель опроса (опционально)
|
||||||
|
/// </summary>
|
||||||
public int? CreatedBy { get; set; }
|
public int? CreatedBy { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,16 @@
|
||||||
namespace SurveyBackend.DTOs;
|
namespace SurveyBackend.DTOs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Схема авторизации пользователя
|
||||||
|
/// </summary>
|
||||||
public record UserLoginDto
|
public record UserLoginDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Почта
|
||||||
|
/// </summary>
|
||||||
public required string Email { get; set; }
|
public required string Email { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Пароль
|
||||||
|
/// </summary>
|
||||||
public required string Password { get; set; }
|
public required string Password { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,32 @@
|
||||||
namespace SurveyBackend.DTOs;
|
namespace SurveyBackend.DTOs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Схема регистрации пользователя
|
||||||
|
/// </summary>
|
||||||
public record UserRegistrationDto
|
public record UserRegistrationDto
|
||||||
{
|
{
|
||||||
public string Email { get; set; }
|
/// <summary>
|
||||||
|
/// Почта
|
||||||
|
/// </summary>
|
||||||
|
public required string Email { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Юзернейм
|
||||||
|
/// </summary>
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Имя
|
||||||
|
/// </summary>
|
||||||
public string FirstName { get; set; }
|
public string FirstName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Фамилия
|
||||||
|
/// </summary>
|
||||||
public string LastName { get; set; }
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Пароль
|
||||||
|
/// </summary>
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace SurveyBackend.Filters;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class EndpointAuthRequirementFilter : IOperationFilter
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
|
{
|
||||||
|
if (!context.ApiDescription
|
||||||
|
.ActionDescriptor
|
||||||
|
.EndpointMetadata
|
||||||
|
.OfType<AuthorizeAttribute>()
|
||||||
|
.Any())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
operation.Security = new List<OpenApiSecurityRequirement>
|
||||||
|
{
|
||||||
|
new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
[new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = JwtBearerDefaults.AuthenticationScheme
|
||||||
|
}
|
||||||
|
}] = new List<string>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,16 @@ using SurveyBackend.DTOs;
|
||||||
|
|
||||||
namespace SurveyBackend.Mappers;
|
namespace SurveyBackend.Mappers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Маппер всего связанного с авторизацией
|
||||||
|
/// </summary>
|
||||||
public static class AuthMapper
|
public static class AuthMapper
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Перегнать схему регистрации в нового юзера
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static User UserRegistrationToModel(UserRegistrationDto dto) => new User
|
public static User UserRegistrationToModel(UserRegistrationDto dto) => new User
|
||||||
{
|
{
|
||||||
Email = dto.Email,
|
Email = dto.Email,
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,18 @@ using SurveyLib.Core.Models.QuestionVariants;
|
||||||
|
|
||||||
namespace SurveyBackend.Mappers;
|
namespace SurveyBackend.Mappers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Маппер всего про вопросы
|
||||||
|
/// </summary>
|
||||||
public static class QuestionMapper
|
public static class QuestionMapper
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Создание вопроса в модель
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <param name="surveyId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="BadRequestException"></exception>
|
||||||
public static QuestionBase QuestionCreationToModel(CreateQuestionDto dto, int surveyId)
|
public static QuestionBase QuestionCreationToModel(CreateQuestionDto dto, int surveyId)
|
||||||
{
|
{
|
||||||
return dto.QuestionType.ToLower() switch
|
return dto.QuestionType.ToLower() switch
|
||||||
|
|
@ -32,6 +42,11 @@ public static class QuestionMapper
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Модель в выходную схему
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="question"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static OutputQuestionDto ModelToQuestionDto(QuestionBase question)
|
public static OutputQuestionDto ModelToQuestionDto(QuestionBase question)
|
||||||
{
|
{
|
||||||
var withAnswerVariants = question.GetType() != typeof(TextQuestion);
|
var withAnswerVariants = question.GetType() != typeof(TextQuestion);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,17 @@ using SurveyLib.Core.Models;
|
||||||
|
|
||||||
namespace SurveyBackend.Mappers;
|
namespace SurveyBackend.Mappers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Маппер всего про опросы
|
||||||
|
/// </summary>
|
||||||
public static class SurveyMapper
|
public static class SurveyMapper
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Схема создания в модель
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static Survey CreateDtoToModel(CreateSurveyDto dto, int userId)
|
public static Survey CreateDtoToModel(CreateSurveyDto dto, int userId)
|
||||||
{
|
{
|
||||||
return new Survey
|
return new Survey
|
||||||
|
|
@ -15,6 +24,11 @@ public static class SurveyMapper
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Модель в выходную схему
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="survey"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static OutputSurveyDto ModelToOutputDto(Survey survey)
|
public static OutputSurveyDto ModelToOutputDto(Survey survey)
|
||||||
{
|
{
|
||||||
return new OutputSurveyDto
|
return new OutputSurveyDto
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,29 @@ using SurveyBackend.Services.Exceptions;
|
||||||
|
|
||||||
namespace SurveyBackend.Middlewares;
|
namespace SurveyBackend.Middlewares;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Имбовая миддлваря, ловит все эксепшны, кастомные прокидывает как HTTP-exception, остальные кидает 502 и кайфуем
|
||||||
|
/// </summary>
|
||||||
public class ExceptionsMiddleware
|
public class ExceptionsMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly ILogger<ExceptionsMiddleware> _logger;
|
private readonly ILogger<ExceptionsMiddleware> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ну типа конструктор хз
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="next"></param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
public ExceptionsMiddleware(RequestDelegate next, ILogger<ExceptionsMiddleware> logger)
|
public ExceptionsMiddleware(RequestDelegate next, ILogger<ExceptionsMiddleware> logger)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext context)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using SurveyBackend.Contexts;
|
||||||
using SurveyBackend.Core.Contexts;
|
using SurveyBackend.Core.Contexts;
|
||||||
using SurveyBackend.Core.Repositories;
|
using SurveyBackend.Core.Repositories;
|
||||||
using SurveyBackend.Core.Services;
|
using SurveyBackend.Core.Services;
|
||||||
|
using SurveyBackend.Filters;
|
||||||
using SurveyBackend.Infrastructure.Data;
|
using SurveyBackend.Infrastructure.Data;
|
||||||
using SurveyBackend.Infrastructure.Repositories;
|
using SurveyBackend.Infrastructure.Repositories;
|
||||||
using SurveyBackend.Middlewares;
|
using SurveyBackend.Middlewares;
|
||||||
|
|
@ -84,20 +85,11 @@ public class Program
|
||||||
Name = "Authorization",
|
Name = "Authorization",
|
||||||
Type = SecuritySchemeType.ApiKey
|
Type = SecuritySchemeType.ApiKey
|
||||||
});
|
});
|
||||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
|
||||||
{
|
c.OperationFilter<EndpointAuthRequirementFilter>();
|
||||||
{
|
|
||||||
new OpenApiSecurityScheme
|
var filePath = Path.Combine(System.AppContext.BaseDirectory, "SurveyBackend.API.xml");
|
||||||
{
|
c.IncludeXmlComments(filePath);
|
||||||
Reference = new OpenApiReference
|
|
||||||
{
|
|
||||||
Type = ReferenceType.SecurityScheme,
|
|
||||||
Id = JwtBearerDefaults.AuthenticationScheme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Array.Empty<string>()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,14 @@
|
||||||
<RootNamespace>SurveyBackend</RootNamespace>
|
<RootNamespace>SurveyBackend</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<DocumentationFile>bin\Debug\SurveyBackend.API.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<DocumentationFile>bin\Release\SurveyBackend.API.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Update="appsettings.*.json">
|
<Content Update="appsettings.*.json">
|
||||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class SurveyService : ISurveyService
|
||||||
public async Task UpdateSurveyAsync(Survey survey)
|
public async Task UpdateSurveyAsync(Survey survey)
|
||||||
{
|
{
|
||||||
if (survey.CreatedBy != _userContext.UserId)
|
if (survey.CreatedBy != _userContext.UserId)
|
||||||
throw new UnauthorizedAccessException("You are not authorized to update this survey.");
|
throw new UnauthorizedException("You are not authorized to update this survey.");
|
||||||
await _surveyRepository.UpdateAsync(survey);
|
await _surveyRepository.UpdateAsync(survey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ public class SurveyService : ISurveyService
|
||||||
|
|
||||||
if (survey.CreatedBy != _userContext.UserId)
|
if (survey.CreatedBy != _userContext.UserId)
|
||||||
{
|
{
|
||||||
throw new UnauthorizedAccessException("You are not authorized to delete this survey.");
|
throw new UnauthorizedException("You are not authorized to delete this survey.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await _surveyRepository.DeleteAsync(survey);
|
await _surveyRepository.DeleteAsync(survey);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue