From 78900ab7ad5504c8154013074589f198750b5bc6 Mon Sep 17 00:00:00 2001 From: majed adel Date: Mon, 20 Jan 2025 07:17:35 -0800 Subject: [PATCH] Add Identity configuration, DTOs and Mappers -Configured Identity using a custom User model to manage authentication and authorization, to be used in the project. - Added multiple DTOs (Data Transfer Objects). - Added multiple Mappers ( manual mapping). - Updated AppDbContext and User model to fully integrate with Identity framework for user management. -Added relationships between models. Note : no migration yet --- survey-beta/DTOs/Create/CreateAnswerDto.cs | 9 +++++ survey-beta/DTOs/Create/CreateChoiceDto.cs | 9 +++++ survey-beta/DTOs/Create/CreateQuestionDto.cs | 9 +++++ survey-beta/DTOs/Create/CreateResponseDto.cs | 9 +++++ survey-beta/DTOs/Create/CreateSurveyDto.cs | 12 ++++++ survey-beta/DTOs/Create/CreateUserDto.cs | 10 +++++ survey-beta/DTOs/Create/LoginDto.cs | 8 ++++ survey-beta/DTOs/Default/AnswerDto.cs | 10 +++++ survey-beta/DTOs/Default/ChoiceDto.cs | 10 +++++ survey-beta/DTOs/Default/QuestionDto.cs | 10 +++++ survey-beta/DTOs/Default/ResponseDto.cs | 10 +++++ survey-beta/DTOs/Default/SurveyDto.cs | 15 +++++++ survey-beta/DTOs/Default/UserDto.cs | 11 +++++ survey-beta/DataBaseContext/AppDbContext.cs | 9 +++-- survey-beta/Mappers/AnswerMapper.cs | 30 ++++++++++++++ survey-beta/Mappers/ChoiceMapper.cs | 31 +++++++++++++++ survey-beta/Mappers/QuestionMapper.cs | 29 ++++++++++++++ survey-beta/Mappers/ResponseMapper.cs | 29 ++++++++++++++ survey-beta/Mappers/SurveyMapper.cs | 37 +++++++++++++++++ survey-beta/Mappers/UserMapper.cs | 42 ++++++++++++++++++++ survey-beta/Models/User.cs | 6 ++- survey-beta/Program.cs | 11 ++++- 22 files changed, 350 insertions(+), 6 deletions(-) create mode 100644 survey-beta/DTOs/Create/CreateAnswerDto.cs create mode 100644 survey-beta/DTOs/Create/CreateChoiceDto.cs create mode 100644 survey-beta/DTOs/Create/CreateQuestionDto.cs create mode 100644 survey-beta/DTOs/Create/CreateResponseDto.cs create mode 100644 survey-beta/DTOs/Create/CreateSurveyDto.cs create mode 100644 survey-beta/DTOs/Create/CreateUserDto.cs create mode 100644 survey-beta/DTOs/Create/LoginDto.cs create mode 100644 survey-beta/DTOs/Default/AnswerDto.cs create mode 100644 survey-beta/DTOs/Default/ChoiceDto.cs create mode 100644 survey-beta/DTOs/Default/QuestionDto.cs create mode 100644 survey-beta/DTOs/Default/ResponseDto.cs create mode 100644 survey-beta/DTOs/Default/SurveyDto.cs create mode 100644 survey-beta/DTOs/Default/UserDto.cs create mode 100644 survey-beta/Mappers/AnswerMapper.cs create mode 100644 survey-beta/Mappers/ChoiceMapper.cs create mode 100644 survey-beta/Mappers/QuestionMapper.cs create mode 100644 survey-beta/Mappers/ResponseMapper.cs create mode 100644 survey-beta/Mappers/SurveyMapper.cs create mode 100644 survey-beta/Mappers/UserMapper.cs diff --git a/survey-beta/DTOs/Create/CreateAnswerDto.cs b/survey-beta/DTOs/Create/CreateAnswerDto.cs new file mode 100644 index 0000000..5fce9c5 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateAnswerDto.cs @@ -0,0 +1,9 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateAnswerDto + { + public string ResponseId { get; set; } + public string QuestionId { get; set; } + public string ChoiceId { get; set; } + } +} diff --git a/survey-beta/DTOs/Create/CreateChoiceDto.cs b/survey-beta/DTOs/Create/CreateChoiceDto.cs new file mode 100644 index 0000000..0da9a56 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateChoiceDto.cs @@ -0,0 +1,9 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateChoiceDto + { + public string Letter { get; set; } + public string Content { get; set; } + public string QuestionId { get; set; } = Guid.NewGuid().ToString(); + } +} diff --git a/survey-beta/DTOs/Create/CreateQuestionDto.cs b/survey-beta/DTOs/Create/CreateQuestionDto.cs new file mode 100644 index 0000000..daf6778 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateQuestionDto.cs @@ -0,0 +1,9 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateQuestionDto + { + public string Content { get; set; } + public string SurveyId { get; set; } = Guid.NewGuid().ToString(); + public ICollection Choices { get; set; } + } +} diff --git a/survey-beta/DTOs/Create/CreateResponseDto.cs b/survey-beta/DTOs/Create/CreateResponseDto.cs new file mode 100644 index 0000000..b3c9dc4 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateResponseDto.cs @@ -0,0 +1,9 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateResponseDto + { + public string IpAddress { get; set; } + public string SurveyId { get; set; } + public ICollection Answers { get; set; } + } +} diff --git a/survey-beta/DTOs/Create/CreateSurveyDto.cs b/survey-beta/DTOs/Create/CreateSurveyDto.cs new file mode 100644 index 0000000..142d738 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateSurveyDto.cs @@ -0,0 +1,12 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateSurveyDto + { + public string Id { get; set; } = Guid.NewGuid().ToString(); + public string Title { get; set; } + public string Description { get; set; } + public string Category { get; set; } + public DateTime ExpirationDate { get; set; } + public ICollection Questions { get; set; } + } +} diff --git a/survey-beta/DTOs/Create/CreateUserDto.cs b/survey-beta/DTOs/Create/CreateUserDto.cs new file mode 100644 index 0000000..00a7957 --- /dev/null +++ b/survey-beta/DTOs/Create/CreateUserDto.cs @@ -0,0 +1,10 @@ +namespace survey_beta.DTOs.Create +{ + public class CreateUserDto + { + public string? Email { get; set; } + public string? Username { get; set; } + public string? Fullname { get; set; } + public string? Password { get; set; } + } +} diff --git a/survey-beta/DTOs/Create/LoginDto.cs b/survey-beta/DTOs/Create/LoginDto.cs new file mode 100644 index 0000000..e867a67 --- /dev/null +++ b/survey-beta/DTOs/Create/LoginDto.cs @@ -0,0 +1,8 @@ +namespace survey_beta.DTOs.Create +{ + public class LoginDto + { + public string UserName { get; set; } + public string Password { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/AnswerDto.cs b/survey-beta/DTOs/Default/AnswerDto.cs new file mode 100644 index 0000000..0dc7ced --- /dev/null +++ b/survey-beta/DTOs/Default/AnswerDto.cs @@ -0,0 +1,10 @@ +namespace survey_beta.DTOs.Default +{ + public class AnswerDto + { + public string Id { get; set; } + public string ResponseId { get; set; } + public string QuestionId { get; set; } + public string ChoiceId { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/ChoiceDto.cs b/survey-beta/DTOs/Default/ChoiceDto.cs new file mode 100644 index 0000000..546acd7 --- /dev/null +++ b/survey-beta/DTOs/Default/ChoiceDto.cs @@ -0,0 +1,10 @@ +namespace survey_beta.DTOs.Default +{ + public class ChoiceDto + { + public string Id { get; set; } + public string Letter { get; set; } + public string Content { get; set; } + public string QuestionId { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/QuestionDto.cs b/survey-beta/DTOs/Default/QuestionDto.cs new file mode 100644 index 0000000..c9ca914 --- /dev/null +++ b/survey-beta/DTOs/Default/QuestionDto.cs @@ -0,0 +1,10 @@ +namespace survey_beta.DTOs.Default +{ + public class QuestionDto + { + public string Id { get; set; } + public string Content { get; set; } + public string SurveyId { get; set; } + public ICollection Choices { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/ResponseDto.cs b/survey-beta/DTOs/Default/ResponseDto.cs new file mode 100644 index 0000000..8b7b5c4 --- /dev/null +++ b/survey-beta/DTOs/Default/ResponseDto.cs @@ -0,0 +1,10 @@ +namespace survey_beta.DTOs.Default +{ + public class ResponseDto + { + public string Id { get; set; } + public string IpAddress { get; set; } + public string SurveyId { get; set; } + public ICollection Answers { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/SurveyDto.cs b/survey-beta/DTOs/Default/SurveyDto.cs new file mode 100644 index 0000000..4fa587b --- /dev/null +++ b/survey-beta/DTOs/Default/SurveyDto.cs @@ -0,0 +1,15 @@ +namespace survey_beta.DTOs.Default +{ + public class SurveyDto + { + public string Id { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string Category { get; set; } + public DateTime ExpirationDate { get; set; } + public bool IsPublished { get; set; } + public string AuthorId { get; set; } + public ICollection Questions { get; set; } + public ICollection Responses { get; set; } + } +} diff --git a/survey-beta/DTOs/Default/UserDto.cs b/survey-beta/DTOs/Default/UserDto.cs new file mode 100644 index 0000000..da5964c --- /dev/null +++ b/survey-beta/DTOs/Default/UserDto.cs @@ -0,0 +1,11 @@ +namespace survey_beta.DTOs.Default +{ + public class UserDto + { + public string? Id { get; set; } + public string? Email { get; set; } + public string? Username { get; set; } + public string? Fullname { get; set; } + public ICollection AuthoredSurveys { get; set; } + } +} diff --git a/survey-beta/DataBaseContext/AppDbContext.cs b/survey-beta/DataBaseContext/AppDbContext.cs index efca097..fa9ada9 100644 --- a/survey-beta/DataBaseContext/AppDbContext.cs +++ b/survey-beta/DataBaseContext/AppDbContext.cs @@ -1,10 +1,13 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using survey_beta.Models; + namespace survey_beta.DataBaseContext { - public class AppDbContext : DbContext + public class AppDbContext : IdentityDbContext + { - public DbSet Users { get; set; } + public override DbSet Users { get; set; } public DbSet Surveys { get; set; } public DbSet Questions { get; set; } public DbSet Choices { get; set; } diff --git a/survey-beta/Mappers/AnswerMapper.cs b/survey-beta/Mappers/AnswerMapper.cs new file mode 100644 index 0000000..37b1a9c --- /dev/null +++ b/survey-beta/Mappers/AnswerMapper.cs @@ -0,0 +1,30 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; + +namespace survey_beta.Mappers +{ + public class AnswerMapper + { + public static AnswerDto ToDto(Answer answer) + { + return new AnswerDto + { + Id = answer.Id, + ResponseId = answer.ResponseId, + QuestionId = answer.QuestionId, + ChoiceId = answer.ChoiceId + }; + } + public static Answer ToEntity(CreateAnswerDto dto) + { + return new Answer + { + Id = Guid.NewGuid().ToString(), + ResponseId = dto.ResponseId, + QuestionId = dto.QuestionId, + ChoiceId = dto.ChoiceId + }; + } + } +} diff --git a/survey-beta/Mappers/ChoiceMapper.cs b/survey-beta/Mappers/ChoiceMapper.cs new file mode 100644 index 0000000..67677a0 --- /dev/null +++ b/survey-beta/Mappers/ChoiceMapper.cs @@ -0,0 +1,31 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; + +namespace survey_beta.Mappers +{ + public class ChoiceMapper + { + public static ChoiceDto ToDto(Choice choice) + { + return new ChoiceDto + { + Id = choice.Id, + Letter = choice.Letter, + Content = choice.Content, + QuestionId = choice.QuestionId + }; + } + + public static Choice ToEntity(CreateChoiceDto dto) + { + return new Choice + { + Id = Guid.NewGuid().ToString(), + Letter = dto.Letter, + Content = dto.Content, + QuestionId = dto.QuestionId + }; + } + } +} diff --git a/survey-beta/Mappers/QuestionMapper.cs b/survey-beta/Mappers/QuestionMapper.cs new file mode 100644 index 0000000..82e4121 --- /dev/null +++ b/survey-beta/Mappers/QuestionMapper.cs @@ -0,0 +1,29 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; + +namespace survey_beta.Mappers +{ + public class QuestionMapper + { + public static QuestionDto ToDto(Question question) + { + return new QuestionDto + { + Id = question.Id, + Content = question.Content, + SurveyId = question.SurveyId + }; + } + + public static Question ToEntity(CreateQuestionDto dto) + { + return new Question + { + Id = Guid.NewGuid().ToString(), + Content = dto.Content, + SurveyId = dto.SurveyId + }; + } + } +} diff --git a/survey-beta/Mappers/ResponseMapper.cs b/survey-beta/Mappers/ResponseMapper.cs new file mode 100644 index 0000000..c6f94c7 --- /dev/null +++ b/survey-beta/Mappers/ResponseMapper.cs @@ -0,0 +1,29 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; + +namespace survey_beta.Mappers +{ + public class ResponseMapper + { + public static ResponseDto ToDto(Response response) + { + return new ResponseDto + { + Id = response.Id, + IpAddress = response.IpAddress, + SurveyId = response.SurveyId + }; + } + + public static Response ToEntity(CreateResponseDto dto) + { + return new Response + { + Id = Guid.NewGuid().ToString(), + IpAddress = dto.IpAddress, + SurveyId = dto.SurveyId + }; + } + } +} diff --git a/survey-beta/Mappers/SurveyMapper.cs b/survey-beta/Mappers/SurveyMapper.cs new file mode 100644 index 0000000..971b5c0 --- /dev/null +++ b/survey-beta/Mappers/SurveyMapper.cs @@ -0,0 +1,37 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; + +namespace survey_beta.Mappers +{ + public class SurveyMapper + { + public static SurveyDto ToDto(Survey survey) + { + return new SurveyDto + { + Id = survey.Id, + Title = survey.Title, + Description = survey.Description, + Category = survey.Category, + ExpirationDate = survey.ExpirationDate, + IsPublished = survey.IsPublished, + AuthorId = survey.AuthorId + }; + } + + public static Survey ToEntity(CreateSurveyDto dto, string authorId) + { + return new Survey + { + Id = Guid.NewGuid().ToString(), + Title = dto.Title, + Description = dto.Description, + Category = dto.Category, + ExpirationDate = dto.ExpirationDate, + IsPublished = false, + AuthorId = authorId + }; + } + } +} diff --git a/survey-beta/Mappers/UserMapper.cs b/survey-beta/Mappers/UserMapper.cs new file mode 100644 index 0000000..b5c9adb --- /dev/null +++ b/survey-beta/Mappers/UserMapper.cs @@ -0,0 +1,42 @@ +using survey_beta.DTOs.Create; +using survey_beta.DTOs.Default; +using survey_beta.Models; +using System.Security.Cryptography; +namespace survey_beta.Mappers +{ + public class UserMapper + { + public static UserDto ToDto(User user) + { + return new UserDto + { + Id = user.Id, + Email = user.Email, + Username = user.Username, + Fullname = user.Fullname + }; + } + public static User ToEntity(CreateUserDto dto) + { + return new User + { + Id = Guid.NewGuid().ToString(), + Email = dto.Email, + Username = dto.Username, + Fullname = dto.Fullname, + PasswordHash = HashPassword(dto.Password) + }; + } + public static string HashPassword(string password) + { + using (var sha256 = SHA256.Create()) + { + var passwordBytes = System.Text.Encoding.UTF8.GetBytes(password); + + var hashBytes = sha256.ComputeHash(passwordBytes); + + return Convert.ToBase64String(hashBytes); + } + } + } +} diff --git a/survey-beta/Models/User.cs b/survey-beta/Models/User.cs index 98691f7..3e0501a 100644 --- a/survey-beta/Models/User.cs +++ b/survey-beta/Models/User.cs @@ -1,6 +1,8 @@ -namespace survey_beta.Models +using Microsoft.AspNetCore.Identity; + +namespace survey_beta.Models { - public class User + public class User : IdentityUser { public string? Id { get; set; } public string? Username { get; set; } diff --git a/survey-beta/Program.cs b/survey-beta/Program.cs index e84aade..3a214fc 100644 --- a/survey-beta/Program.cs +++ b/survey-beta/Program.cs @@ -1,21 +1,30 @@ +using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using survey_beta.DataBaseContext; +using survey_beta.Models; +using survey_beta.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); - builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); var app = builder.Build(); // Configure the HTTP request pipeline. +builder.Services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + +builder.Services.AddScoped(); app.UseHttpsRedirection(); +app.UseAuthentication(); + app.UseAuthorization(); app.MapControllers();