update-current-user WIP

This commit is contained in:
Dominic Villemure
2024-06-29 22:45:17 -04:00
committed by Jonathan Bourdon
parent 72e243cf84
commit 5282fcfd49
13 changed files with 855 additions and 34 deletions

View File

@@ -1,21 +1,27 @@
using Google.Apis.Oauth2.v2.Data; using Google.Apis.Oauth2.v2.Data;
using Hutopy.Application.Common.Models; using Hutopy.Application.Common.Models;
using Hutopy.Application.Users.Models;
namespace Hutopy.Application.Common.Interfaces; namespace Hutopy.Application.Common.Interfaces;
public interface IIdentityService public interface IIdentityService
{ {
Task<string?> GetUserNameAsync(string userId); Task<Result<string>> CreateUserAsync(Userinfo userInfo);
Task<Result> CreateUserAsync(string email, string userName, string firstName, string lastName, string password); Task<Result<string>> CreateUserAsync(string email, string userName, string firstName, string lastName, string password);
Task<UserModel?> FindUserByIdAsync(string id);
Task<UserModel?> GetCurrentUserAsync(); Task<UserModel?> GetCurrentUserAsync();
Task<UserModel?> FindUserByEmailAsync(string id); Task<Result<string>> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation,
Task<string?> LoginAsync(string email, string password); string phoneNumber, string birthDate, string country, string city, string address, string about,
string description,
SocialNetworksModel socialNetworks);
Task<IList<string>> GetCurrentUserRolesAsync();
Task<UserModel?> FindUserByIdAsync(string id);
Task<UserModel?> FindUserByEmailAsync(string email);
Task<UserModel?> GetUserByUserNameAsync(string userName); Task<UserModel?> GetUserByUserNameAsync(string userName);
Task<string?> LoginAsync(string email, string password);
Task<bool> IsInRoleAsync(string userId, string role); Task<bool> IsInRoleAsync(string userId, string role);
Task<bool> AuthorizeAsync(string userId, string policyName); Task<bool> AuthorizeAsync(string userId, string policyName);
Task<string?> GetUserNameAsync(string userId);
Task<Result> AddRoleAsync(string userId, string role); Task<Result> AddRoleAsync(string userId, string role);
Task<IList<string>> GetCurrentUserRolesAsync();
Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo);
Task<Result> DeleteUserAsync(string userId); Task<Result> DeleteUserAsync(string userId);
} }

View File

@@ -5,9 +5,8 @@ public class Result(
IEnumerable<string> errors) IEnumerable<string> errors)
{ {
public bool Succeeded { get; init; } = succeeded; public bool Succeeded { get; init; } = succeeded;
public string[] Errors { get; init; } = errors.ToArray(); public string[] Errors { get; init; } = errors.ToArray();
public static Result Success() public static Result Success()
{ {
return new Result(true, Array.Empty<string>()); return new Result(true, Array.Empty<string>());
@@ -18,3 +17,27 @@ public class Result(
return new Result(false, errors); return new Result(false, errors);
} }
} }
public class Result<T>(
bool succeeded,
IEnumerable<string> errors)
{
public bool Succeeded { get; init; } = succeeded;
public string[] Errors { get; init; } = errors.ToArray();
public T? Value { get; set; }
public T GetValueOrDefault()
{
return Value ?? default(T)!;
}
public static Result<T> Success()
{
return new Result<T>(true, Array.Empty<string>());
}
public static Result<T> Failure(IEnumerable<string> errors)
{
return new Result<T>(false, errors);
}
}

View File

@@ -1,3 +1,5 @@
using Hutopy.Application.Users.Models;
namespace Hutopy.Application.Common.Models; namespace Hutopy.Application.Common.Models;
// TODO: Review nullable affectation here // TODO: Review nullable affectation here
@@ -7,6 +9,15 @@ public class UserModel
public string? UserName { get; set; } public string? UserName { get; set; }
public string? FirstName { get; set; } public string? FirstName { get; set; }
public string? LastName { get; set; } public string? LastName { get; set; }
public string? Email { get; set; } public string? Occupation { get; set; }
public string? Email { get; init; } = String.Empty;
public string? Phone { get; init; } = String.Empty;
public string? BirthDate { get; init; } = String.Empty;
public string? Country { get; init; } = String.Empty;
public string? City { get; init; } = String.Empty;
public string? Address { get; init; } = String.Empty;
public string? About { get; init; } = String.Empty;
public string? Description { get; init; } = String.Empty;
public SocialNetworksModel SocialNetworks { get; init; } = new();
public string? PortraitUrl { get; set; } public string? PortraitUrl { get; set; }
} }

View File

@@ -0,0 +1,40 @@
using Hutopy.Application.Common.Interfaces;
using Hutopy.Application.Users.Models;
namespace Hutopy.Application.Users.Commands;
public class UpdateCurrentUserCommand : IRequest<string>
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required string Occupation { get; init; }
public required string PhoneNumber { get; init; }
public required string BirthDate { get; init; }
public required string Country { get; init; }
public required string City { get; init; }
public required string Address { get; init; }
public required string About { get; init; }
public required string Description { get; init; }
public required SocialNetworksModel SocialNetworks { get; init; }
}
public class UpdateCurrentUserCommandHandler(IApplicationDbContext context, IIdentityService identityService) :
IRequestHandler<UpdateCurrentUserCommand, string>
{
public async Task<string> Handle(UpdateCurrentUserCommand request, CancellationToken cancellationToken)
{
var identityUser = await identityService.GetCurrentUserAsync();
if (identityUser?.Id is null) return string.Empty;
var result = await identityService.UpdateCurrentUserAsync(identityUser.Id, request.FirstName, request.LastName,
request.Occupation, request.PhoneNumber, request.BirthDate,
request.Country, request.City, request.Address, request.About,
request.Description, request.SocialNetworks);
await context.SaveChangesAsync(cancellationToken);
return result.GetValueOrDefault();
}
}

View File

@@ -0,0 +1,13 @@
namespace Hutopy.Application.Users.Models;
public class SocialNetworksModel
{
public string FacebookUrl { get; init; } = String.Empty;
public string InstagramUrl { get; init; } = String.Empty;
public string XUrl { get; init; } = String.Empty;
public string LinkedInUrl { get; init; } = String.Empty;
public string TikTokUrl { get; init; } = String.Empty;
public string YoutubeUrl { get; init; } = String.Empty;
public string RedditUrl { get; init; } = String.Empty;
public string YourWebsiteUrl { get; init; } = String.Empty;
}

View File

@@ -28,12 +28,22 @@ public class GetCurrentUserQueryHandler(
var user = new UserDto var user = new UserDto
{ {
Id = currentUserId, Id = currentUserId,
FirstName = identityUser?.FirstName ?? "", FirstName = identityUser.FirstName ?? "",
LastName = identityUser?.LastName ?? "", LastName = identityUser.LastName ?? "",
UserName = identityUser?.UserName ?? "", UserName = identityUser.UserName ?? "",
Occupation = identityUser.Occupation ?? "",
Phone = identityUser.Phone ?? "",
Email = identityUser.Email ?? "",
BirthDate = identityUser.BirthDate ?? "",
Country = identityUser.Country ?? "",
City = identityUser.City ?? "",
Address = identityUser.Address ?? "",
About = identityUser.About ?? "",
Description = identityUser.Description ?? "",
SocialNetworks = identityUser.SocialNetworks,
UserTransactions = transactions, UserTransactions = transactions,
TotalBalance = transactions.Sum(x => x.Amount), TotalBalance = transactions.Sum(x => x.Amount),
UserRoles = roles UserRoles = roles,
}; };
return user; return user;

View File

@@ -1,3 +1,5 @@
using Hutopy.Application.Users.Models;
namespace Hutopy.Application.Users.Queries.GetCurrentUser; namespace Hutopy.Application.Users.Queries.GetCurrentUser;
public class UserDto public class UserDto
@@ -6,6 +8,16 @@ public class UserDto
public required string FirstName { get; init; } public required string FirstName { get; init; }
public required string LastName { get; init; } public required string LastName { get; init; }
public string UserName { get; init; } = String.Empty; public string UserName { get; init; } = String.Empty;
public string Occupation { get; init; } = String.Empty;
public string Email { get; init; } = String.Empty;
public string Phone { get; init; } = String.Empty;
public string BirthDate { get; init; } = String.Empty;
public string Country { get; init; } = String.Empty;
public string City { get; init; } = String.Empty;
public string Address { get; init; } = String.Empty;
public string About { get; init; } = String.Empty;
public string Description { get; init; } = String.Empty;
public SocialNetworksModel SocialNetworks { get; init; } = new();
public List<UserTransactionDto> UserTransactions { get; init; } = []; public List<UserTransactionDto> UserTransactions { get; init; } = [];
public IList<string> UserRoles { get; init; } = []; public IList<string> UserRoles { get; init; } = [];
public required decimal TotalBalance { get; init; } public required decimal TotalBalance { get; init; }

View File

@@ -7,5 +7,12 @@ public class ApplicationUser : IdentityUser
{ {
public string FirstName { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty;
public string Occupation { get; set; } = string.Empty;
public string BirthDate { get; set; } = string.Empty;
public string Country { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public string About { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public SocialNetworks SocialNetworks { get; set; } = new(); public SocialNetworks SocialNetworks { get; set; } = new();
} }

View File

@@ -3,6 +3,8 @@ using Google.Apis.Oauth2.v2.Data;
using System.Security.Claims; using System.Security.Claims;
using Hutopy.Application.Common.Interfaces; using Hutopy.Application.Common.Interfaces;
using Hutopy.Application.Common.Models; using Hutopy.Application.Common.Models;
using Hutopy.Application.Users.Models;
using Hutopy.Infrastructure.Identity.OwnedEntities;
using Hutopy.Infrastructure.Utils; using Hutopy.Infrastructure.Utils;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@@ -45,23 +47,10 @@ public class IdentityService(
return userModel; return userModel;
} }
public async Task<(Result Result, string UserId)> CreateUserAsync(string userName, string password)
{
var user = new ApplicationUser
{
UserName = userName,
Email = userName,
};
var result = await userManager.CreateAsync(user, password);
return (result.ToApplicationResult(), user.Id);
}
public async Task<(Result Result, string UserId)> CreateUserAsync(Userinfo userInfo) public async Task<Result<string>> CreateUserAsync(Userinfo userInfo)
{ {
var user = new ApplicationUser var applicationUser = new ApplicationUser
{ {
UserName = userInfo.Name, UserName = userInfo.Name,
Email = userInfo.Email, Email = userInfo.Email,
@@ -71,12 +60,18 @@ public class IdentityService(
var password = Guid.NewGuid().ToString("N")[..32]; var password = Guid.NewGuid().ToString("N")[..32];
var result = await userManager.CreateAsync(user, password); var identityResult = await userManager.CreateAsync(applicationUser, password);
return (result.ToApplicationResult(), user.Id); var applicationResult = identityResult.ToApplicationResult();
var result = new Result<string>(applicationResult.Succeeded, applicationResult.Errors);
result.Value = applicationUser.Id;
return result;
} }
public async Task<Result> CreateUserAsync(string email, string userName, string firstName, string lastName, string password) public async Task<Result<string>> CreateUserAsync(string email, string userName, string firstName, string lastName, string password)
{ {
var applicationUser = new ApplicationUser var applicationUser = new ApplicationUser
{ {
@@ -88,7 +83,52 @@ public class IdentityService(
var response = await userManager.CreateAsync(applicationUser, password); var response = await userManager.CreateAsync(applicationUser, password);
return response.ToApplicationResult(); var result = new Result<string>(response.Succeeded, response.ToApplicationResult().Errors);
result.Value = applicationUser.Id;
return result;
}
public async Task<Result<string>> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation,
string phoneNumber, string birthDate, string country, string city, string address, string about, string description,
SocialNetworksModel socialNetworks)
{
var applicationUser = await userManager.FindByIdAsync(id);
if (applicationUser is null) return Result<string>.Failure(new[] { "User not found." });
applicationUser.FirstName = firstName;
applicationUser.LastName = lastName;
applicationUser.Occupation = occupation;
applicationUser.PhoneNumber = phoneNumber;
applicationUser.BirthDate = birthDate;
applicationUser.Country = country;
applicationUser.City = city;
applicationUser.Address = address;
applicationUser.About = about;
applicationUser.Description = description;
applicationUser.SocialNetworks = new SocialNetworks()
{
FacebookUrl = socialNetworks.FacebookUrl,
InstagramUrl = socialNetworks.InstagramUrl,
XUrl = socialNetworks.XUrl,
LinkedInUrl = socialNetworks.LinkedInUrl,
TikTokUrl = socialNetworks.TikTokUrl,
YoutubeUrl = socialNetworks.YoutubeUrl,
RedditUrl = socialNetworks.RedditUrl,
YourWebsiteUrl = socialNetworks.YourWebsiteUrl
};
var response = await userManager.UpdateAsync(applicationUser);
var applicationResult = response.ToApplicationResult();
var result = new Result<string>(applicationResult.Succeeded,
applicationResult.Errors);
result.Value = id;
return result;
} }
public async Task<UserModel?> FindUserByIdAsync(string id) public async Task<UserModel?> FindUserByIdAsync(string id)
@@ -97,13 +137,32 @@ public class IdentityService(
if (response == null) return null; if (response == null) return null;
var userModel = new UserModel() var userModel = new UserModel
{ {
Id = response.Id, Id = response.Id,
UserName = response.UserName, UserName = response.UserName,
FirstName = response.FirstName, FirstName = response.FirstName,
LastName = response.LastName, LastName = response.LastName,
Email = response.Email, Email = response.Email,
Occupation = response.Occupation,
Phone = response.PhoneNumber,
BirthDate = response.BirthDate,
Country = response.Country,
City = response.City,
Address = response.Address,
About = response.About,
Description = response.Description,
SocialNetworks = new SocialNetworksModel
{
FacebookUrl = response.SocialNetworks.FacebookUrl,
InstagramUrl = response.SocialNetworks.InstagramUrl,
XUrl = response.SocialNetworks.XUrl,
LinkedInUrl = response.SocialNetworks.LinkedInUrl,
TikTokUrl = response.SocialNetworks.TikTokUrl,
YoutubeUrl = response.SocialNetworks.YoutubeUrl,
RedditUrl = response.SocialNetworks.RedditUrl,
YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl,
}
}; };
return userModel; return userModel;

View File

@@ -0,0 +1,497 @@
// <auto-generated />
using System;
using Hutopy.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Hutopy.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20240630001806_AddMissingInformationsToUser")]
partial class AddMissingInformationsToUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Hutopy.Domain.Entities.FutureCreator", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTimeOffset>("Created")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("EmailAddress")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("datetimeoffset");
b.Property<string>("LastModifiedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ReasonToJoin")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SocialNetworkAccount")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("FutureCreators");
});
modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("decimal(18,2)");
b.Property<string>("ApplicationUserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<DateTimeOffset>("Created")
.HasColumnType("datetimeoffset");
b.Property<string>("CreatedBy")
.HasColumnType("nvarchar(max)");
b.Property<string>("Currency")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsConfirmed")
.HasColumnType("bit");
b.Property<DateTimeOffset>("LastModified")
.HasColumnType("datetimeoffset");
b.Property<string>("LastModifiedBy")
.HasColumnType("nvarchar(max)");
b.Property<bool>("Paid")
.HasColumnType("bit");
b.Property<string>("StripeBillingDetailEmail")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeBillingDetailName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeChargeId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeEventId")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripePaymentIntent")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripePaymentMethod")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeReceiptUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("TipMessage")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("ApplicationUserId");
b.ToTable("UserTransactions");
});
modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("About")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("Address")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("BirthDate")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("City")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Country")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Occupation")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Hutopy.Domain.Entities.UserTransaction", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("ApplicationUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Hutopy.Infrastructure.Identity.ApplicationUser", b =>
{
b.OwnsOne("Hutopy.Infrastructure.Identity.OwnedEntities.SocialNetworks", "SocialNetworks", b1 =>
{
b1.Property<string>("ApplicationUserId")
.HasColumnType("nvarchar(450)");
b1.Property<string>("FacebookUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("InstagramUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("LinkedInUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("RedditUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("TikTokUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("XUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("YourWebsiteUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.Property<string>("YoutubeUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b1.HasKey("ApplicationUserId");
b1.ToTable("ApplicationUser_SocialNetworks", (string)null);
b1.WithOwner()
.HasForeignKey("ApplicationUserId");
});
b.Navigation("SocialNetworks")
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Hutopy.Infrastructure.Identity.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,95 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Hutopy.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddMissingInformationsToUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "About",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Address",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "BirthDate",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "City",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Country",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Description",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Occupation",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "About",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Address",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "BirthDate",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "City",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Country",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Description",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Occupation",
table: "AspNetUsers");
}
}
}

View File

@@ -149,13 +149,37 @@ namespace Hutopy.Infrastructure.Migrations
b.Property<string>("Id") b.Property<string>("Id")
.HasColumnType("nvarchar(450)"); .HasColumnType("nvarchar(450)");
b.Property<string>("About")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("AccessFailedCount") b.Property<int>("AccessFailedCount")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("Address")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("BirthDate")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("City")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyStamp") b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken() .IsConcurrencyToken()
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<string>("Country")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email") b.Property<string>("Email")
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("nvarchar(256)");
@@ -185,6 +209,10 @@ namespace Hutopy.Infrastructure.Migrations
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("nvarchar(256)");
b.Property<string>("Occupation")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash") b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");

View File

@@ -0,0 +1,20 @@
using Hutopy.Application.Users.Commands;
namespace Hutopy.Web.Endpoints;
public class UpdateMyUser : EndpointGroupBase
{
public override void Map(WebApplication app)
{
app.MapGroup(this)
.RequireAuthorization()
.MapPatch("/profile", UpdateCurrentUser);
}
private static async Task<string> UpdateCurrentUser(ISender sender, UpdateCurrentUserCommand command)
{
return await sender.Send(command);
}
}