577 lines
22 KiB
C#
577 lines
22 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Newtonsoft.Json.Linq;
|
||
using System.Security.Claims;
|
||
using System.Text.Json;
|
||
using AyCode.Core.Consts;
|
||
using AyCode.Core.Extensions;
|
||
using TIAMWebApp.Shared.Application.Models;
|
||
using TIAMWebApp.Shared.Application.Models.PageModels;
|
||
using TIAMWebApp.Server.Models;
|
||
using AyCode.Core.Loggers;
|
||
using TIAM.Database.DataLayers.Users;
|
||
using TIAM.Entities.Users;
|
||
using TIAM.Models.Dtos.Users;
|
||
using TIAM.Entities.Profiles;
|
||
using TIAM.Entities.Addresses;
|
||
using TIAM.Services.Server.Logins;
|
||
using ILogger = TIAM.Core.Loggers.ILogger;
|
||
using AyCode.Core.Helpers;
|
||
using AyCode.Entities;
|
||
using AyCode.Services.SignalRs;
|
||
using TIAM.Models.Server.Logins;
|
||
using TIAM.Services;
|
||
using TIAM.Services.Interfaces;
|
||
using TIAMWebApp.Shared.Application.Services;
|
||
using GoogleApi.Entities.Search.Video.Common;
|
||
using TIAM.Database.DataLayers.Admins;
|
||
using TIAM.Entities.Emails;
|
||
using TIAMWebApp.Shared.Application.Models.ClientSide.Messages;
|
||
using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||
using System.Net;
|
||
using TIAM.Services.Server;
|
||
|
||
namespace TIAMWebApp.Server.Controllers
|
||
{
|
||
[Authorize]
|
||
[ApiController]
|
||
[Route("api/v1/[controller]")]
|
||
public class UserAPIController(IConfiguration configuration, AdminDal adminDal, UserDal userDal, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters) : ControllerBase, IUserApiControllerCommon
|
||
{
|
||
private readonly TIAM.Core.Loggers.Logger<UserAPIController> _logger = new(logWriters.ToArray());
|
||
|
||
private LoginService _loginService = new LoginService(userDal, configuration);
|
||
//private readonly IWebHostEnvironment _webHostEnvironment;
|
||
//readonly PasswordHasher _hasher = new();
|
||
|
||
//private readonly ILogger _logger;
|
||
/*private UserModel[] users = new UserModel[]
|
||
{
|
||
new UserModel(new Guid("540271f6-c604-4c16-8160-d5a7cafedf00"), "test@tiam.hu", "+36701234567", "Asdasd123456"),
|
||
new UserModel(new Guid("4cbaed43-2465-4d99-84f1-c8bc6b7025f7"), "adam@tiam.hu", "+36701234567", "Asdasd987654")
|
||
|
||
};*/
|
||
|
||
//[AllowAnonymous]
|
||
//[HttpPost]
|
||
//[Route(APIUrls.LoggerRouteName)]
|
||
//public async Task AddLogItem(AcLogItem? logItem)
|
||
//{
|
||
// if (logItem == null)
|
||
// {
|
||
// _logger.Error("AddLogItem; LogItem == null");
|
||
// //_logger.Writer<ConsoleLogWriter>().Detail("");
|
||
|
||
// return;
|
||
// }
|
||
|
||
// //logItem.LogHeaderId = ???
|
||
// logItem.TimeStampUtc = DateTime.UtcNow;
|
||
|
||
// _logger.Write(logItem);
|
||
|
||
// //_logger.Writer<IAcConsoleLogWriter>()?.Write(logItem.AppType, logItem.LogLevel, logItem.Text, logItem.CallerName, logItem.CategoryName, logItem.ErrorType, logItem.Exception);
|
||
// //_logger.Writer<DbLogItemWriter>().WriteLogItemAsync(logItem);
|
||
//}
|
||
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.LogoutUserRouteName)]
|
||
public async Task<IActionResult> LogoutUser([FromBody] string refreshToken)
|
||
{
|
||
_logger.Info(@"LogoutUser called");
|
||
_logger.Info($"refreshtoken: {refreshToken}");
|
||
_loginService.Logout();
|
||
|
||
//TODO: Implement<6E>lni a Logout-ot kliens <20>s szerver oldalon is! - J.
|
||
return Ok("OK");
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.AuthenticateUserRouteName)]
|
||
public async Task<IActionResult> AuthenticateUser([FromBody] JsonElement serializedLoginModel)
|
||
{
|
||
_logger.Info(@"AuthenticateUser called");
|
||
var authenticateUser = JObject.Parse(serializedLoginModel.GetRawText()).ToObject<LoginModel>();
|
||
|
||
if (authenticateUser == null) throw new NullReferenceException("authenticateUser == null");
|
||
|
||
_logger.Info(authenticateUser.Email);
|
||
|
||
var loggedInModel = _loginService.Login(authenticateUser.Email, authenticateUser.Password);
|
||
if (loggedInModel.IsLoggedIn)
|
||
{
|
||
var response = new MainResponse
|
||
{
|
||
Content = new AuthenticationResponse
|
||
{
|
||
RefreshToken = loggedInModel.LoggedInUser.RefreshToken,
|
||
AccessToken = loggedInModel.AccessToken
|
||
},
|
||
|
||
IsSuccess = true,
|
||
ErrorMessage = ""
|
||
};
|
||
|
||
return Ok(response);
|
||
}
|
||
|
||
_logger.Warning(@"User not valid! errorCode: " + loggedInModel.LoginErrorCode);
|
||
return Unauthorized();
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.RefreshTokenRouteName)]
|
||
public async Task<IActionResult> RefreshToken(RefreshTokenRequest? refreshTokenRequest)
|
||
{
|
||
_logger.Info(@"RefreshToken called");
|
||
|
||
var response = new MainResponse();
|
||
if (refreshTokenRequest is null)
|
||
{
|
||
_logger.Info(@"RefreshTokenRequest is null");
|
||
response.ErrorMessage = "Invalid request";
|
||
return BadRequest(response);
|
||
}
|
||
|
||
var principal = _loginService.GetPrincipalFromExpiredToken(refreshTokenRequest.AccessToken);
|
||
|
||
if (principal != null)
|
||
{
|
||
_logger.Info(@"Principal is not null");
|
||
var email = principal.Claims.FirstOrDefault(f => f.Type == ClaimTypes.Email);
|
||
|
||
//var userModel = await _userManager.FindByEmailAsync(email?.Value);
|
||
//UserModel? user = users.FirstOrDefault(x => x.Email == email?.Value);
|
||
User? dbUser = null;
|
||
|
||
if (email != null)
|
||
{
|
||
//get user from db
|
||
dbUser = await userDal.GetUserByEmailAsync(email.Value, true);
|
||
_logger.Info($@"DbUser email: {dbUser?.EmailAddress}");
|
||
}
|
||
|
||
//mocking - update userModel with new refreshToken so it returns true after the check below
|
||
//dbUser.RefreshToken = refreshTokenRequest.RefreshToken;
|
||
|
||
if (dbUser is null || dbUser.RefreshToken != refreshTokenRequest.RefreshToken)
|
||
{
|
||
response.ErrorMessage = "Invalid Request";
|
||
_logger.Info($@"{dbUser?.RefreshToken}, {refreshTokenRequest.RefreshToken}");
|
||
return BadRequest(response);
|
||
}
|
||
|
||
var newAccessToken = _loginService.GenerateAccessToken(dbUser);
|
||
var refreshToken = _loginService.GenerateRefreshToken();
|
||
|
||
//mocking - update userModel with new refreshToken
|
||
dbUser.RefreshToken = refreshToken;
|
||
//TODO await _userManager.UpdateAsync(userModel);
|
||
await userDal.UpdateJwtRefreshTokenAsync(dbUser.EmailAddress, dbUser.RefreshToken);
|
||
|
||
response.IsSuccess = true;
|
||
response.Content = new AuthenticationResponse
|
||
{
|
||
RefreshToken = refreshToken,
|
||
AccessToken = newAccessToken
|
||
};
|
||
|
||
return Ok(response);
|
||
}
|
||
|
||
_logger.Info(@"Principal is null");
|
||
return NotFound("Invalid Token Found");
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route("CreateUser")]
|
||
public async Task<IActionResult> CreateUser([FromBody] JsonElement serializedRegistrationModel)
|
||
{
|
||
_logger.Info(@"CreateUser called");
|
||
|
||
if (string.IsNullOrEmpty(serializedRegistrationModel.GetRawText()))
|
||
{
|
||
return BadRequest("SerializedLoginModel is required");
|
||
}
|
||
else
|
||
{
|
||
var user = JObject.Parse(serializedRegistrationModel.GetRawText()).ToObject<RegistrationModel>();
|
||
bool result = false;
|
||
if (user != null)
|
||
{
|
||
//add userModel to users array
|
||
//Array.Resize(ref users, users.Length + 1);
|
||
//users[users.Length - 1] = new UserModel(user.Email, user.PhoneNumber, user.Password);
|
||
|
||
|
||
var userId = Guid.NewGuid();
|
||
var email = user?.Email;
|
||
var phoneNumber = user?.PhoneNumber;
|
||
var password = user?.Password;
|
||
|
||
if (email is null || phoneNumber is null || password is null)
|
||
{
|
||
return BadRequest("Invalid request");
|
||
}
|
||
else
|
||
{
|
||
_logger.Info($@"User to be created: {userId}");
|
||
_logger.Info($@"User to be created: {email}");
|
||
_logger.Info($@"User to be created: {phoneNumber}");
|
||
_logger.Info($@"User to be created: {password}");
|
||
//var hashedPassword = PasswordHasher.HashPassword(user.Password, PasswordHasher.GenerateDynamicSalt(userId));
|
||
//await _userDal.CreateUserAsync(new User(userId, email, phoneNumber, hashedPassword));
|
||
var createResult = await _loginService.RegistrationAsync(userId, email, password, phoneNumber);
|
||
if (createResult != AyCode.Core.Consts.AcErrorCode.Unset)
|
||
{
|
||
_logger.Error("Error:" + createResult.ToString());
|
||
result = false;
|
||
}
|
||
else
|
||
{
|
||
result = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return Ok(result.ToString());
|
||
}
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.CreateGuestUserRouteName)]
|
||
public async Task<IActionResult> CreateGuestUser([FromBody] JsonElement serializedRegistrationModel)
|
||
{
|
||
_logger.Info(@"CreateGuestUser called");
|
||
UserModelDtoDetail? guestUser = null;
|
||
|
||
if (string.IsNullOrEmpty(serializedRegistrationModel.GetRawText()))
|
||
{
|
||
return BadRequest("SerializedLoginModel is required");
|
||
}
|
||
|
||
var user = JObject.Parse(serializedRegistrationModel.GetRawText()).ToObject<RegistrationModel>();
|
||
|
||
if (user != null)
|
||
{
|
||
//var random = new Random();
|
||
//var chars = "1234567890";
|
||
//var nameExtension = new string(Enumerable.Repeat(chars, 10)
|
||
// .Select(s => s[random.Next(s.Length)]).ToArray());
|
||
|
||
|
||
var userId = Guid.NewGuid();
|
||
var email = user.Email?.ToLower();
|
||
var phoneNumber = user.PhoneNumber;
|
||
var password = user.Password;
|
||
|
||
var referralId = user.ReferralId.IsNullOrEmpty() ? null : user.ReferralId;
|
||
|
||
if (email is null || phoneNumber is null || password is null)
|
||
{
|
||
return BadRequest("Invalid request");
|
||
}
|
||
|
||
_logger.Info($@"User to be created: {userId}");
|
||
_logger.Info($@"User to be created: {email}");
|
||
_logger.Info($@"User to be created: {phoneNumber}");
|
||
_logger.Info($@"User to be created: {password}");
|
||
|
||
var createResult = await _loginService.RegistrationAsync(userId, email, password, phoneNumber, referralId);
|
||
if (createResult != AyCode.Core.Consts.AcErrorCode.Unset)
|
||
{
|
||
_logger.Error("Error:" + createResult.ToString());
|
||
}
|
||
else
|
||
{
|
||
}
|
||
}
|
||
|
||
return Ok(guestUser);
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpGet]
|
||
[Route("GetUsers")]
|
||
public async Task<List<UserModelDto>> GetUsers()
|
||
{
|
||
//var users = await _userDal.Ctx.Users.ToListAsync();//.GetUsersAsync();
|
||
//return users;
|
||
return await userDal.GetAllUserModelDtoAsync<UserModelDto>();
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpGet]
|
||
[Route(APIUrls.GetUsersWithDetailsRouteName)]
|
||
[SignalR(SignalRTags.GetAllUserModelDtoDetails)]
|
||
public async Task<List<UserModelDtoDetail>> GetUsersWithDetails()
|
||
{
|
||
_logger.Info("GetUsersWithDetails called");
|
||
|
||
var users = await userDal.GetAllUserModelDtoAsync<UserModelDtoDetail>();
|
||
return users;
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.GetAllUsers)]
|
||
public async Task<List<User>> GetAllUsers()
|
||
{
|
||
_logger.Info("GetAllUsers called");
|
||
return await userDal.GetUsersAsync();
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.GetAllUserModelDtoEmails)]
|
||
public async Task<List<UserModelDtoEmail>> GetUserModelDtoEmails()
|
||
{
|
||
_logger.Info("GetUserModelDtoEmails called");
|
||
|
||
return await userDal.GetUserModelDtoEmailsAsync();
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.UpdateUser)]
|
||
[SignalR(SignalRTags.UpdateUser)]
|
||
public async Task<User?> UpdateUser([FromBody] User user)
|
||
{
|
||
_logger.Info("UpdateUser called");
|
||
|
||
return await userDal.UpdateUserAsync(user);
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.UserChangePassword)]
|
||
public async Task<UserModelDtoDetail?> UserChangePassword([FromBody] ChangePasswordDto changePasswordDto)
|
||
{
|
||
_logger.Info("ChangeUserPassword called");
|
||
|
||
var errorCode = await _loginService.ChangePasswordAsync(changePasswordDto.UserId, changePasswordDto.OldPassword, changePasswordDto.NewPassword);
|
||
|
||
if (errorCode == AcErrorCode.Unset)
|
||
return await userDal.GetUserModelDtoByIdAsync<UserModelDtoDetail>(changePasswordDto.UserId, true);
|
||
|
||
_logger.Error($"ErrorCode: {errorCode}; userId: {changePasswordDto.UserId}");
|
||
return null;
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.UserForgotPassword)]
|
||
public async Task<UserModelDtoDetail?> UserForgotPassword([FromBody] ForgotPasswordDto forgotPasswordDto)
|
||
{
|
||
_logger.Info("UserForgotPassword called");
|
||
|
||
var errorCode = await _loginService.ForgotPasswordAsync(forgotPasswordDto.Email, forgotPasswordDto.NewPassword);
|
||
|
||
if (errorCode == AcErrorCode.Unset)
|
||
return await userDal.GetUserModelDtoByEmailAsync<UserModelDtoDetail>(forgotPasswordDto.Email, true);
|
||
|
||
_logger.Error($"ErrorCode: {errorCode}; email: {forgotPasswordDto.Email}");
|
||
return null;
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.UpdateUserModelDtoDetail)]
|
||
public async Task<UserModelDtoDetail?> UpdateUserModelDtoDetail(UserModelDtoDetail userModelDtoDetail)
|
||
{
|
||
_logger.Info($"UpdateUserModelDtoDetail called; Id: {userModelDtoDetail.UserDto.Id}");
|
||
|
||
var result = await userDal.UpdateUserModelDtoDetailAsync(userModelDtoDetail);
|
||
return result;
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.AddUser)]
|
||
public async Task<User?> AddUser(User user)
|
||
{
|
||
throw new NotImplementedException("Profile, Address, etc...");
|
||
|
||
if (user.Id.IsNullOrEmpty()) user.Id = Guid.NewGuid();
|
||
|
||
_logger.Info($"AddUser called; Id: {user.Id}");
|
||
|
||
return await userDal.AddUserAsync(user) ? user : null;
|
||
}
|
||
|
||
[NonAction]
|
||
[SignalR(SignalRTags.AddUserModelDtoDetail)]
|
||
public async Task<UserModelDtoDetail?> AddUserModelDtoDetail(UserModelDtoDetail userModelDtoDetail)
|
||
{
|
||
throw new NotImplementedException("Profile, Address, etc...");
|
||
|
||
if (userModelDtoDetail.UserDto.Id.IsNullOrEmpty()) userModelDtoDetail.UserDto.Id = Guid.NewGuid();
|
||
|
||
_logger.Info($"AddUserModelDtoDetail called; Id: {userModelDtoDetail.UserDto.Id}");
|
||
|
||
var result = await userDal.AddUserModelDtoDetailAsync(userModelDtoDetail);
|
||
return result;
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpGet]
|
||
[Route(APIUrls.GetUserByEmailRouteName + "/{email}")]
|
||
public async Task<UserModelDto>? GetUserByEmail(string email)
|
||
{
|
||
_logger.Info($"GetUserByEmail called with email: {email}");
|
||
var result = await userDal.GetUserModelDtoByEmailAsync<UserModelDto>(email, false);
|
||
if (result == null)
|
||
{
|
||
UserModelDto resultDto = new UserModelDto();
|
||
return resultDto;
|
||
}
|
||
else
|
||
{
|
||
return result;
|
||
}
|
||
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.GetUserByIdRouteName)]
|
||
public async Task<UserModelDto?> GetUserById([FromBody] Guid id)
|
||
{
|
||
_logger.Info($"GetUserById called with id: {id}");
|
||
return await userDal.GetUserModelDtoByIdAsync<UserModelDto>(id, true);
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.GetUserDetailByIdRouteName)]
|
||
public async Task<UserModelDtoDetail?> GetUserDetailById([FromBody] Guid id)
|
||
{
|
||
_logger.Info($"GetUserDetailById called with id: {id}");
|
||
var result = await userDal.GetUserModelDtoByIdAsync<UserModelDtoDetail>(id, false);
|
||
return result;
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.SendForgottenPasswordMailRouteName)]
|
||
public async Task<bool> SendForgottenPasswordMail([FromBody] string email)
|
||
{
|
||
User user;
|
||
_logger.Info($"SendForgottenPasswordMail called with id: {email}");
|
||
user = await userDal.GetUserByEmailAsync(email, false);
|
||
if (user == null)
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
//create new token for the user
|
||
//user.ConfirmToken = Guid.NewGuid().ToString("N");
|
||
user.ConfirmToken = AcCharsGenerator.NewToken();
|
||
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
|
||
var result = await adminDal.UpdateUserAsync(user);
|
||
_logger.Debug($"Saved token for user: {result.ConfirmToken}");
|
||
//send email
|
||
|
||
_logger.Info($"Created transfer, send emailMessage!!!");
|
||
var message = new MessageSenderModel<EmailMessage>();
|
||
message.Message = new EmailMessage();
|
||
message.Message.EmailAddress = email;
|
||
message.Message.Id = Guid.NewGuid();
|
||
message.MessageType = AyCode.Models.Enums.MessageTypesEnum.email;
|
||
message.Message.Subject = "[Tour I Am] New transfer in Budapest";
|
||
message.Message.ContextId = user.Id;
|
||
message.Message.SenderId = Guid.Empty;
|
||
message.Message.Recipients.Add(new EmailRecipient(Guid.NewGuid(), user.Id, Guid.NewGuid(), email));
|
||
|
||
message.Message.Text = EmailTemplateHelper.GenerateForgotPasswordEmail(user.FullName, Setting.BaseUrl, user.Id.ToString(), user.ConfirmToken);
|
||
_logger.Info(message.Message.Text);
|
||
var messageElement = message.Message;
|
||
Console.WriteLine(message.Message);
|
||
var mailResult = await messageSenderService.SendMessageAsync(messageElement, (int)message.MessageType);
|
||
await adminDal.AddEmailMessageAsync(messageElement);
|
||
_logger.Info("SendEmail result: " + mailResult);
|
||
//-----------------
|
||
if (mailResult == HttpStatusCode.OK.ToString())
|
||
{
|
||
await adminDal.AddEmailMessageAsync(messageElement);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.ValidateForgottenPasswordTokenRouteName)]
|
||
public async Task<string> ValidateForgottenPasswordToken([FromBody] string[] parameters)
|
||
{
|
||
User? user;
|
||
_logger.Info($"ValidateForgottenPasswordToken called with id: {parameters[0]}");
|
||
if (parameters != null && parameters[0] != null && parameters[1] != null)
|
||
{
|
||
user = await userDal.GetUserByIdAsync(Guid.Parse(parameters[0]), false);
|
||
if (user == null)
|
||
{
|
||
return "User not found";
|
||
}
|
||
else
|
||
{
|
||
if (parameters[1] == user.ConfirmToken)
|
||
{
|
||
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
|
||
//if user is not email validated, set email valid
|
||
if (!user.EmailConfirmed)
|
||
await SetEmailConfirmedMethod(user);
|
||
|
||
return "Success";
|
||
|
||
}
|
||
else
|
||
{
|
||
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
|
||
return "Invalid token";
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return "Invalid request";
|
||
}
|
||
|
||
}
|
||
|
||
[AllowAnonymous]
|
||
[HttpPost]
|
||
[Route(APIUrls.SetEmailConfirmedRouteName)]
|
||
public async Task<bool> SetEmailConfirmed([FromBody] Guid userId)
|
||
{
|
||
_logger.Info($"SetEmailConfirmed called with id: {userId}");
|
||
if(User!= null)
|
||
{
|
||
var user = await userDal.GetUserByIdAsync(userId, false);
|
||
return await SetEmailConfirmedMethod(user);
|
||
|
||
}
|
||
return false;
|
||
}
|
||
|
||
[NonAction]
|
||
private async Task<bool> SetEmailConfirmedMethod(User user)
|
||
{
|
||
user.EmailConfirmed = true;
|
||
var result = await adminDal.UpdateUserAsync(user);
|
||
if (result != null)
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
}
|
||
|
||
} |