Merge branch 'features/finish-authorization-backend' into 'unstable'
Add authorization See merge request internship-2025/survey-webapp/survey-webapp!5
This commit is contained in:
commit
43feaae7f3
28 changed files with 1164 additions and 13 deletions
|
|
@ -1,5 +1,7 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using SurveyBackend.Core.Services;
|
||||
using SurveyBackend.DTOs;
|
||||
using SurveyBackend.Mappers.UserDTOs;
|
||||
|
||||
namespace SurveyBackend.Controllers;
|
||||
|
||||
|
|
@ -7,9 +9,24 @@ namespace SurveyBackend.Controllers;
|
|||
[Route("auth")]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> GetToken([FromBody] UserLoginDto loginData)
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
|
||||
public AuthController(IAuthorizationService authorizationService)
|
||||
{
|
||||
return Ok();
|
||||
_authorizationService = authorizationService;
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> LogIn([FromBody] UserLoginDto loginData)
|
||||
{
|
||||
var token = await _authorizationService.LogInUser(loginData.Email, loginData.Password);
|
||||
return Ok(new { token = token });
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register([FromBody] UserRegistrationDto registerData)
|
||||
{
|
||||
var token = await _authorizationService.RegisterUser(UserRegistrationMapper.UserRegistrationToModel(registerData));
|
||||
return Ok(new { token = token });
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using SurveyBackend.Core.Models;
|
||||
using SurveyBackend.Core.Services;
|
||||
using SurveyBackend.DTOs;
|
||||
|
||||
namespace SurveyBackend.Mappers.UserDTOs;
|
||||
|
||||
public static class UserRegistrationMapper
|
||||
{
|
||||
public static User UserRegistrationToModel(UserRegistrationDto dto) => new User
|
||||
{
|
||||
Email = dto.Email,
|
||||
FirstName = dto.FirstName,
|
||||
LastName = dto.LastName,
|
||||
Password = dto.Password,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using SurveyBackend.Services.Exceptions;
|
||||
|
||||
namespace SurveyBackend.Middlewares;
|
||||
|
||||
public class ExceptionsMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<ExceptionsMiddleware> _logger;
|
||||
|
||||
public ExceptionsMiddleware(RequestDelegate next, ILogger<ExceptionsMiddleware> logger)
|
||||
{
|
||||
_next = next;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
context.Response.StatusCode = ex.StatusCode;
|
||||
context.Response.ContentType = "application/json";
|
||||
|
||||
var response = new
|
||||
{
|
||||
error = ex.Message
|
||||
};
|
||||
|
||||
await context.Response.WriteAsJsonAsync(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.ContentType = "application/json";
|
||||
|
||||
var response = new
|
||||
{
|
||||
error = "Internal Server Error. GG WP, request bub fix"
|
||||
};
|
||||
|
||||
await context.Response.WriteAsJsonAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,14 @@ using System.Text;
|
|||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using SurveyBackend.Core.Repositories;
|
||||
using SurveyBackend.Core.Services;
|
||||
using SurveyBackend.Infrastructure;
|
||||
using SurveyBackend.Infrastructure.Data;
|
||||
using SurveyBackend.Infrastructure.Repositories;
|
||||
using SurveyBackend.Middlewares;
|
||||
using SurveyBackend.Services;
|
||||
using SurveyBackend.Services.Services;
|
||||
using SurveyLib.Core.Repositories;
|
||||
using SurveyLib.Core.Services;
|
||||
using SurveyLib.Infrastructure.EFCore.Data;
|
||||
|
|
@ -27,6 +33,13 @@ public class Program
|
|||
|
||||
builder.Services.AddScoped<SurveyDbContext>(provider => provider.GetRequiredService<ApplicationDbContext>());
|
||||
|
||||
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
||||
builder.Services.AddScoped<IUserService, UserService>();
|
||||
|
||||
builder.Services.AddScoped<IPasswordHasher, Sha256PasswordHasher>();
|
||||
|
||||
builder.Services.AddScoped<IAuthorizationService, AuthorizationService>();
|
||||
|
||||
builder.Services.AddScoped<ISurveyRepository, SurveyRepository>();
|
||||
builder.Services.AddScoped<ISurveyService, SurveyService>();
|
||||
|
||||
|
|
@ -59,6 +72,8 @@ public class Program
|
|||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseMiddleware<ExceptionsMiddleware>();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,18 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.2"/>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.15" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SurveyBackend.Core\SurveyBackend.Core.csproj" />
|
||||
<ProjectReference Include="..\SurveyBackend.Infrastructure\SurveyBackend.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\SurveyBackend.Services\SurveyBackend.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace SurveyBackend.Core.Models;
|
|||
|
||||
public class User
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
|
|
|
|||
|
|
@ -4,4 +4,5 @@ namespace SurveyBackend.Core.Repositories;
|
|||
|
||||
public interface IUserRepository : IGenericRepository<User>
|
||||
{
|
||||
public Task<User?> GetUserByEmail(string email);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using SurveyBackend.Core.Models;
|
||||
|
||||
namespace SurveyBackend.Core.Services;
|
||||
|
||||
public interface IAuthorizationService
|
||||
{
|
||||
public Task<string> LogInUser(string email, string password);
|
||||
public Task<string> RegisterUser(User user);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace SurveyBackend.Infrastructure.Services;
|
||||
namespace SurveyBackend.Core.Services;
|
||||
|
||||
public interface IPasswordHasher
|
||||
{
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
using SurveyBackend.Core.Models;
|
||||
|
||||
namespace SurveyBackend.Core.Services;
|
||||
|
||||
public interface IUserService
|
||||
{
|
||||
|
||||
public Task<User> GetUserByEmail(string email);
|
||||
public Task<bool> IsEmailTaken(string email);
|
||||
public Task CreateUserAsync(User user);
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.15" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
321
SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418123442_Initial.Designer.cs
generated
Normal file
321
SurveyBackend/SurveyBackend.Infrastructure/Data/Migrations/20250418123442_Initial.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
// <auto-generated />
|
||||
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("20250418123442_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.15");
|
||||
|
||||
modelBuilder.Entity("GroupUser", b =>
|
||||
{
|
||||
b.Property<int>("GroupsId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UsersId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("GroupsId", "UsersId");
|
||||
|
||||
b.HasIndex("UsersId");
|
||||
|
||||
b.ToTable("GroupUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyBackend.Core.Models.Group", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyBackend.Core.Models.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.Answer", b =>
|
||||
{
|
||||
b.Property<int>("CompletionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("QuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("AnswerText")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("CompletionId", "QuestionId");
|
||||
|
||||
b.HasIndex("QuestionId");
|
||||
|
||||
b.ToTable("Answers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.AnswerVariant", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("MultipleAnswerQuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("QuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("SingleAnswerQuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("FinishedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SurveyId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SurveyId");
|
||||
|
||||
b.ToTable("Completions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.QuestionBase", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Discriminator")
|
||||
.IsRequired()
|
||||
.HasMaxLength(34)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SurveyId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
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.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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SurveyBackend.Infrastructure.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Groups",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Label = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Groups", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Surveys",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Surveys", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Email = table.Column<string>(type: "TEXT", nullable: false),
|
||||
FirstName = table.Column<string>(type: "TEXT", nullable: false),
|
||||
LastName = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Password = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Completions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
SurveyId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
FinishedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Completions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Completions_Surveys_SurveyId",
|
||||
column: x => x.SurveyId,
|
||||
principalTable: "Surveys",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Questions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
SurveyId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Discriminator = table.Column<string>(type: "TEXT", maxLength: 34, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Questions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Questions_Surveys_SurveyId",
|
||||
column: x => x.SurveyId,
|
||||
principalTable: "Surveys",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GroupUser",
|
||||
columns: table => new
|
||||
{
|
||||
GroupsId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
UsersId = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GroupUser", x => new { x.GroupsId, x.UsersId });
|
||||
table.ForeignKey(
|
||||
name: "FK_GroupUser_Groups_GroupsId",
|
||||
column: x => x.GroupsId,
|
||||
principalTable: "Groups",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_GroupUser_Users_UsersId",
|
||||
column: x => x.UsersId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Answers",
|
||||
columns: table => new
|
||||
{
|
||||
CompletionId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
QuestionId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
AnswerText = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Answers", x => new { x.CompletionId, x.QuestionId });
|
||||
table.ForeignKey(
|
||||
name: "FK_Answers_Completions_CompletionId",
|
||||
column: x => x.CompletionId,
|
||||
principalTable: "Completions",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Answers_Questions_QuestionId",
|
||||
column: x => x.QuestionId,
|
||||
principalTable: "Questions",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AnswerVariant",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
QuestionId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Text = table.Column<string>(type: "TEXT", nullable: false),
|
||||
MultipleAnswerQuestionId = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
SingleAnswerQuestionId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AnswerVariant", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AnswerVariant_Questions_MultipleAnswerQuestionId",
|
||||
column: x => x.MultipleAnswerQuestionId,
|
||||
principalTable: "Questions",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_AnswerVariant_Questions_QuestionId",
|
||||
column: x => x.QuestionId,
|
||||
principalTable: "Questions",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_AnswerVariant_Questions_SingleAnswerQuestionId",
|
||||
column: x => x.SingleAnswerQuestionId,
|
||||
principalTable: "Questions",
|
||||
principalColumn: "Id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Answers_QuestionId",
|
||||
table: "Answers",
|
||||
column: "QuestionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AnswerVariant_MultipleAnswerQuestionId",
|
||||
table: "AnswerVariant",
|
||||
column: "MultipleAnswerQuestionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AnswerVariant_QuestionId",
|
||||
table: "AnswerVariant",
|
||||
column: "QuestionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AnswerVariant_SingleAnswerQuestionId",
|
||||
table: "AnswerVariant",
|
||||
column: "SingleAnswerQuestionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Completions_SurveyId",
|
||||
table: "Completions",
|
||||
column: "SurveyId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GroupUser_UsersId",
|
||||
table: "GroupUser",
|
||||
column: "UsersId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Questions_SurveyId",
|
||||
table: "Questions",
|
||||
column: "SurveyId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Answers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AnswerVariant");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GroupUser");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Completions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Questions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Groups");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Surveys");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using SurveyBackend.Infrastructure.Data;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SurveyBackend.Infrastructure.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.15");
|
||||
|
||||
modelBuilder.Entity("GroupUser", b =>
|
||||
{
|
||||
b.Property<int>("GroupsId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UsersId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("GroupsId", "UsersId");
|
||||
|
||||
b.HasIndex("UsersId");
|
||||
|
||||
b.ToTable("GroupUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyBackend.Core.Models.Group", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyBackend.Core.Models.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.Answer", b =>
|
||||
{
|
||||
b.Property<int>("CompletionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("QuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("AnswerText")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("CompletionId", "QuestionId");
|
||||
|
||||
b.HasIndex("QuestionId");
|
||||
|
||||
b.ToTable("Answers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.AnswerVariant", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("MultipleAnswerQuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("QuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("SingleAnswerQuestionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("FinishedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SurveyId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SurveyId");
|
||||
|
||||
b.ToTable("Completions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SurveyLib.Core.Models.QuestionBase", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Discriminator")
|
||||
.IsRequired()
|
||||
.HasMaxLength(34)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SurveyId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
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.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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,4 +41,9 @@ public class UserRepository : IUserRepository
|
|||
_context.Users.Remove(entity);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserByEmail(string email)
|
||||
{
|
||||
return await _context.Users.FirstOrDefaultAsync(u => u.Email == email);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
@ -16,4 +20,8 @@
|
|||
<ProjectReference Include="..\SurveyBackend.Core\SurveyBackend.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\Migrations\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.Text;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace SurveyBackend.Infrastructure;
|
||||
namespace SurveyBackend.Services;
|
||||
|
||||
public static class AuthOptions
|
||||
{
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace SurveyBackend.Services.Exceptions;
|
||||
|
||||
public class ConflictException : ServiceException
|
||||
{
|
||||
public override int StatusCode => 409;
|
||||
|
||||
public ConflictException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace SurveyBackend.Services.Exceptions;
|
||||
|
||||
public class NotFoundException : ServiceException
|
||||
{
|
||||
public override int StatusCode => 404;
|
||||
|
||||
public NotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace SurveyBackend.Services.Exceptions;
|
||||
|
||||
public abstract class ServiceException : Exception
|
||||
{
|
||||
public abstract int StatusCode { get; }
|
||||
|
||||
protected ServiceException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace SurveyBackend.Services.Exceptions;
|
||||
|
||||
public class UnauthorizedException : ServiceException
|
||||
{
|
||||
public override int StatusCode => 401;
|
||||
|
||||
public UnauthorizedException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ using System.Security.Claims;
|
|||
using Microsoft.IdentityModel.Tokens;
|
||||
using SurveyBackend.Core.Models;
|
||||
|
||||
namespace SurveyBackend.Infrastructure.Helpers;
|
||||
namespace SurveyBackend.Services.Helpers;
|
||||
|
||||
public class TokenHelper
|
||||
{
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using SurveyBackend.Core.Models;
|
||||
using SurveyBackend.Core.Services;
|
||||
using SurveyBackend.Services.Exceptions;
|
||||
using SurveyBackend.Services.Helpers;
|
||||
|
||||
namespace SurveyBackend.Services.Services;
|
||||
|
||||
public class AuthorizationService : IAuthorizationService
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IPasswordHasher _passwordHasher;
|
||||
|
||||
public AuthorizationService(IUserService userService, IPasswordHasher passwordHasher)
|
||||
{
|
||||
_userService = userService;
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task<string> LogInUser(string email, string password)
|
||||
{
|
||||
var user = await _userService.GetUserByEmail(email);
|
||||
if (!_passwordHasher.Verify(password, user.Password))
|
||||
{
|
||||
throw new UnauthorizedException("Password is incorrect.");
|
||||
}
|
||||
|
||||
var token = TokenHelper.GetAuthToken(user);
|
||||
return token;
|
||||
}
|
||||
|
||||
public async Task<string> RegisterUser(User user)
|
||||
{
|
||||
var isEmailTaken = await _userService.IsEmailTaken(user.Email);
|
||||
if (isEmailTaken)
|
||||
{
|
||||
throw new ConflictException("Email already exists");
|
||||
}
|
||||
|
||||
user.Password = _passwordHasher.HashPassword(user.Password);
|
||||
|
||||
await _userService.CreateUserAsync(user);
|
||||
var token = TokenHelper.GetAuthToken(user);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Security.Cryptography;
|
||||
using SurveyBackend.Core.Services;
|
||||
|
||||
namespace SurveyBackend.Infrastructure.Services;
|
||||
namespace SurveyBackend.Services.Services;
|
||||
|
||||
public class Sha256PasswordHasher : IPasswordHasher
|
||||
{
|
||||
31
SurveyBackend/SurveyBackend.Services/Services/UserService.cs
Normal file
31
SurveyBackend/SurveyBackend.Services/Services/UserService.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using SurveyBackend.Core.Models;
|
||||
using SurveyBackend.Core.Repositories;
|
||||
using SurveyBackend.Core.Services;
|
||||
using SurveyBackend.Services.Exceptions;
|
||||
|
||||
namespace SurveyBackend.Services.Services;
|
||||
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
|
||||
public UserService(IUserRepository userRepository)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
|
||||
public async Task<User> GetUserByEmail(string email)
|
||||
{
|
||||
return await _userRepository.GetUserByEmail(email) ?? throw new NotFoundException("Email not found");
|
||||
}
|
||||
|
||||
public async Task<bool> IsEmailTaken(string email)
|
||||
{
|
||||
return await _userRepository.GetUserByEmail(email) != null;
|
||||
}
|
||||
|
||||
public async Task CreateUserAsync(User user)
|
||||
{
|
||||
await _userRepository.AddAsync(user);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SurveyBackend.Core\SurveyBackend.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SurveyLib.Infrastructure.EF
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SurveyLib.Core", "..\SurveyLib\SurveyLib.Core\SurveyLib.Core.csproj", "{C17C405B-37CF-48E6-AA44-44B878F4DE56}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SurveyBackend.Services", "SurveyBackend.Services\SurveyBackend.Services.csproj", "{3CDA6495-4FB2-4F07-8B2F-15BFD2A35181}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -36,5 +38,9 @@ Global
|
|||
{C17C405B-37CF-48E6-AA44-44B878F4DE56}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C17C405B-37CF-48E6-AA44-44B878F4DE56}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C17C405B-37CF-48E6-AA44-44B878F4DE56}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3CDA6495-4FB2-4F07-8B2F-15BFD2A35181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3CDA6495-4FB2-4F07-8B2F-15BFD2A35181}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3CDA6495-4FB2-4F07-8B2F-15BFD2A35181}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3CDA6495-4FB2-4F07-8B2F-15BFD2A35181}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7bbc78fbd7eef3bb2497b966ea73eba31aa7032c
|
||||
Subproject commit fe2735da5040501f143526a8c1af19c8023f6368
|
||||
Loading…
Add table
Add a link
Reference in a new issue