AdminDal (?), Registration and login almost finished (works from db already), login approvements, new api endpoints

This commit is contained in:
Adam 2023-11-25 03:17:41 +01:00
parent 4bed3bc4f4
commit 7096c90637
28 changed files with 438 additions and 176 deletions

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using TIAM.Database.DbContexts;
using TIAM.Entities.Users;
namespace TIAM.Database.DataLayers.Users
{
public class AdminDal : TiamDalBase<AdminDbContext>
{
public AdminDal() : base()
{
}
public Task<List<User>> GetUsersAsync()
{
return Ctx.Users.ToListAsync();
}
public Task<User?> GetUserByEmailAsync(string email)
{
Console.WriteLine($"Getting user from db {email}");
var emailLower = email.ToLower();
return Ctx.Users.SingleOrDefaultAsync(x=>x.Email.ToLower() == emailLower);
}
public Task<bool> CreateUserAsync(User user)
{
user.Created = DateTime.UtcNow;
user.Modified = DateTime.UtcNow;
Ctx.Users.Add(user);
Console.WriteLine($"Saving user to db {user.Id}, {user.Email}, {user.PhoneNumber}, {user.Password}");
return Ctx.SaveChangesAsync().ContinueWith(x=>x.Result > 0);
}
public Task<bool> UpdateUserAsync(User user)
{
user.Modified = DateTime.UtcNow;
Ctx.Users.Update(user);
return Ctx.SaveChangesAsync().ContinueWith(x=>x.Result > 0);
}
}
}

View File

@ -7,6 +7,7 @@ using AyCode.Database;
using Microsoft.Identity.Client; using Microsoft.Identity.Client;
using TIAM.Database.DbContexts; using TIAM.Database.DbContexts;
using TIAM.Entities.TransferDestinations; using TIAM.Entities.TransferDestinations;
using TIAM.Entities.Users;
namespace TIAM.Database.DataLayers.TransferDestinations; namespace TIAM.Database.DataLayers.TransferDestinations;
@ -15,4 +16,12 @@ public class TransferDestinationDal : TiamDalBase<TransferDestinationDbContext>
public TransferDestinationDal() : base() public TransferDestinationDal() : base()
{ {
} }
public Task<bool> CreateTransferDestinationAsync(TransferDestination transferDestination)
{
transferDestination.Created = DateTime.UtcNow;
transferDestination.Modified = DateTime.UtcNow;
Ctx.TransferDestinations.Add(transferDestination);
return Ctx.SaveChangesAsync().ContinueWith(x => x.Result > 0);
}
} }

View File

@ -23,8 +23,25 @@ namespace TIAM.Database.DataLayers.Users
public Task<User?> GetUserByEmailAsync(string email) public Task<User?> GetUserByEmailAsync(string email)
{ {
Console.WriteLine($"Getting user from db {email}");
var emailLower = email.ToLower(); var emailLower = email.ToLower();
return Ctx.Users.SingleOrDefaultAsync(x=>x.Email.ToLower() == emailLower); return Ctx.Users.SingleOrDefaultAsync(x=>x.Email.ToLower() == emailLower);
} }
public Task<bool> CreateUserAsync(User user)
{
user.Created = DateTime.UtcNow;
user.Modified = DateTime.UtcNow;
Ctx.Users.Add(user);
Console.WriteLine($"Saving user to db {user.Id}, {user.Email}, {user.PhoneNumber}, {user.Password}");
return Ctx.SaveChangesAsync().ContinueWith(x=>x.Result > 0);
}
public Task<bool> UpdateUserAsync(User user)
{
user.Modified = DateTime.UtcNow;
Ctx.Users.Update(user);
return Ctx.SaveChangesAsync().ContinueWith(x=>x.Result > 0);
}
} }
} }

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Database.DbContexts;
using Microsoft.EntityFrameworkCore;
using TIAM.Entities.TransferDestinations;
using TIAM.Entities.Users;
namespace TIAM.Database.DbContexts
{
public class AdminDbContext : TiamDbContextBase
{
public DbSet<User> Users { get; set; }
public DbSet<TransferDestination> TransferDestinations { get; set; }
public AdminDbContext() //: this(string.Empty)
{
}
public AdminDbContext(string name) : base(name)
{
}
public AdminDbContext(DbContextOptions<DbContext> options, string name) : base(options, name)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableDetailedErrors(true);
base.OnConfiguring(optionsBuilder);
}
}
}

View File

@ -29,7 +29,10 @@ namespace TIAM.Database.DbContexts
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
optionsBuilder.EnableDetailedErrors(true);
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
} }
} }
} }

View File

@ -1,44 +1,30 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using AyCode.Entities.Interfaces; using AyCode.Entities.Interfaces;
using AyCode.Entities.Locations;
using AyCode.Interfaces.TimeStampInfo; using AyCode.Interfaces.TimeStampInfo;
namespace TIAM.Entities.TransferDestinations namespace TIAM.Entities.TransferDestinations
{ {
[Table("TransferDestination")] [Table("TransferDestination")]
public class TransferDestination : IEntityGuid, ITimeStampInfo public class TransferDestination : LocationBase, ITimeStampInfo
{ {
[DatabaseGenerated(DatabaseGeneratedOption.None)] public Guid Id { get; set; }
public Guid Id public double Longitude { get; set; }
{ public double Latitude { get; set; }
get; public string? Address { get; set; }
set; public string? Name { get; set; }
}
public string Name
{
get;
set;
}
public string Description
{
get;
set;
}
public decimal Longitude
{
get;
set;
}
public decimal Latitude
{
get;
set;
}
public DateTime Created { get; set; } public DateTime Created { get; set; }
public DateTime Modified { get; set; } public DateTime Modified { get; set; }
public TransferDestination() { }
public TransferDestination(double longitude, double latitude, string address) : this(Guid.NewGuid(), longitude, latitude, address) { }
public TransferDestination(Guid id, double longitude, double latitude, string address) : base(Guid.NewGuid(), longitude, latitude, address) { }
public TransferDestination(Guid id, string name, double longitude, double latitude, string address) : base(id, longitude, latitude, address) { }
} }
} }

View File

@ -13,5 +13,10 @@ namespace TIAM.Entities.Users
public User(string email, string password) : this(Guid.NewGuid(), email, password) { } public User(string email, string password) : this(Guid.NewGuid(), email, password) { }
public User(Guid id, string email, string password) : base(id, email, password) public User(Guid id, string email, string password) : base(id, email, password)
{ } { }
public User(Guid id, string email, string phoneNumber, string password) : base(id, email, phoneNumber, password)
{ }
public User(Guid id, string email, string phoneNumber, string password, string refreshToken) : base(id, email, phoneNumber, password, refreshToken)
{ }
} }
} }

View File

@ -21,5 +21,16 @@ namespace TIAMMobileApp.Services
{ {
return await SecureStorage.GetAsync(key); return await SecureStorage.GetAsync(key);
} }
public async Task DeleteFromSecureStorageAsync(string key)
{
SecureStorage.Remove(key);
}
public async Task ClearAllSecureStorageAsync()
{
SecureStorage.RemoveAll();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.JSInterop;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text; using System.Text;
@ -7,7 +8,7 @@ using TIAMWebApp.Shared.Application.Interfaces;
using TIAMWebApp.Shared.Application.Models; using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Models.ClientSide; using TIAMWebApp.Shared.Application.Models.ClientSide;
using TIAMWebApp.Shared.Application.Models.PageModels; using TIAMWebApp.Shared.Application.Models.PageModels;
using TIAMWebApp.Shared.Application.Utility;
namespace TIAMMobilApp.Services namespace TIAMMobilApp.Services
{ {
@ -15,6 +16,8 @@ namespace TIAMMobilApp.Services
{ {
private readonly HttpClient http; private readonly HttpClient http;
private readonly ISecureStorageHandler secureStorageHandler; private readonly ISecureStorageHandler secureStorageHandler;
public UserModel? User { get; set; } = new UserModel("", "", ""); public UserModel? User { get; set; } = new UserModel("", "", "");
public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
@ -127,14 +130,14 @@ namespace TIAMMobilApp.Services
return (isSuccess, result); return (isSuccess, result);
} }
public Task<IEnumerable<User>> GetUsersAsync() public async Task<IEnumerable<User>?> GetUsersAsync()
{ {
throw new NotImplementedException(); return await http.GetFromJsonAsync<IEnumerable<User>>(APIUrls.GetUsers);
} }
public Task<User> GetUserByEmailAsync(string email) public async Task<User?> GetUserByEmailAsync(string email)
{ {
throw new NotImplementedException(); return await http.GetFromJsonAsync<User?>(APIUrls.GetUserByEmail);
} }
public async Task<bool> RefreshToken() public async Task<bool> RefreshToken()

View File

@ -1,4 +1,4 @@
@page "/"; @page "/admin";
@using TIAMWebApp.Shared.Application.Interfaces @using TIAMWebApp.Shared.Application.Interfaces
@using TIAMWebApp.Shared.Application.Models @using TIAMWebApp.Shared.Application.Models
@using TIAMWebApp.Shared.Application.Utility @using TIAMWebApp.Shared.Application.Utility
@ -6,9 +6,11 @@
@using System.IdentityModel.Tokens.Jwt @using System.IdentityModel.Tokens.Jwt
@using TIAMWebApp.Shared.Application.Models.ClientSide @using TIAMWebApp.Shared.Application.Models.ClientSide
@inject NavigationManager NavManager @inject NavigationManager NavManager
@inject IJSRuntime JSRuntime
@inject LogToBrowserConsole logToBrowserConsole @inject LogToBrowserConsole logToBrowserConsole
@inject IUserDataService UserDataService @inject IUserDataService UserDataService
@inject ISecureStorageHandler SecureStorageHandler @inject ISecureStorageHandler SecureStorageHandler
@inject HttpClient http;
<h3>AppLaunch</h3> <h3>AppLaunch</h3>
Loading.... Loading....
@ -18,6 +20,11 @@ Loading....
protected async override Task OnInitializedAsync() protected async override Task OnInitializedAsync()
{ {
logToBrowserConsole = new LogToBrowserConsole(JSRuntime);
//wait for 5 seconds
await Task.Delay(5000);
string userDetailsStr = await SecureStorageHandler.GetFromSecureStorageAsync(nameof(Setting.UserBasicDetails)); string userDetailsStr = await SecureStorageHandler.GetFromSecureStorageAsync(nameof(Setting.UserBasicDetails));
logToBrowserConsole.LogToBC(userDetailsStr); logToBrowserConsole.LogToBC(userDetailsStr);
if (!string.IsNullOrWhiteSpace(userDetailsStr)) if (!string.IsNullOrWhiteSpace(userDetailsStr))
@ -25,30 +32,37 @@ Loading....
var userBasicDetail = JsonConvert.DeserializeObject<UserBasicDetails>(userDetailsStr); var userBasicDetail = JsonConvert.DeserializeObject<UserBasicDetails>(userDetailsStr);
var handler = new JwtSecurityTokenHandler(); var handler = new JwtSecurityTokenHandler();
var jsontoken = handler.ReadToken(userBasicDetail.AccessToken) as JwtSecurityToken; var jsontoken = handler.ReadToken(userBasicDetail?.AccessToken) as JwtSecurityToken;
Setting.UserBasicDetails = userBasicDetail;
if (jsontoken.ValidTo < DateTime.UtcNow) if(userBasicDetail!= null)
Setting.UserBasicDetails = userBasicDetail;
if (jsontoken?.ValidTo < DateTime.UtcNow)
{ {
logToBrowserConsole.LogToBC("Token needs to be refreshed");
bool isTokenRefreshed = await UserDataService.RefreshToken(); bool isTokenRefreshed = await UserDataService.RefreshToken();
if (isTokenRefreshed) if (isTokenRefreshed)
{ {
logToBrowserConsole.LogToBC("Token refreshed");
NavManager.NavigateTo("/home"); NavManager.NavigateTo("/home");
} }
else else
{ {
logToBrowserConsole.LogToBC("Couldn't refresh token");
NavManager.NavigateTo("/login"); NavManager.NavigateTo("/login");
} }
} }
else else
{ {
logToBrowserConsole.LogToBC("Valid token found");
NavManager.NavigateTo("/home"); NavManager.NavigateTo("/home");
} }
} }
else else
{ {
logToBrowserConsole.LogToBC("No token stored yet");
NavManager.NavigateTo("/login"); NavManager.NavigateTo("/login");
} }

View File

@ -1,4 +1,4 @@
@page "/index" @page "/"
@using TIAMSharedUI.Shared @using TIAMSharedUI.Shared
<PageTitle>Index</PageTitle> <PageTitle>Index</PageTitle>

View File

@ -57,7 +57,7 @@
} }
} }
<div class="text-center fs-6"> <div class="text-center fs-6">
Already have an account? <a href="login">Sign in here!</a> No account yet? <a href="register">Sign up here!</a>
</div> </div>
</div> </div>
@ -130,7 +130,7 @@
//await App.Current.MainPage.DisplayAlert("Error", "Invalid credentials", "Ok"); //await App.Current.MainPage.DisplayAlert("Error", "Invalid credentials", "Ok");
//display error message via jsinterop //display error message via jsinterop
logToBrowserConsole.LogToBC("Invalid credentials"); logToBrowserConsole.LogToBC("Invalid credentials");
navManager.NavigateTo("login2"); navManager.NavigateTo("login");
} }
else else
{ {
@ -153,7 +153,7 @@
//await App.Current.MainPage.DisplayAlert("Error", "An error occured while trying to login", "Ok"); //await App.Current.MainPage.DisplayAlert("Error", "An error occured while trying to login", "Ok");
//display error message via jsinterop //display error message via jsinterop
logToBrowserConsole.LogToBC("An error occured while trying to login"); logToBrowserConsole.LogToBC("An error occured while trying to login");
navManager.NavigateTo("login2"); navManager.NavigateTo("login");
} }
} }

View File

@ -5,13 +5,10 @@
@inject IJSRuntime jsRuntime @inject IJSRuntime jsRuntime
<div class="page"> <div class="page">
@if (Setting.UserBasicDetails != null)
{
<div class="my-sidebar"> <div class="my-sidebar">
<NavMenu /> <NavMenu />
</div> </div>
}
<main> <main>
<article class="content"> <article class="content">
@ -21,7 +18,6 @@
<TopRow></TopRow> <TopRow></TopRow>
} }
} }
@Body @Body
</article> </article>
</main> </main>

View File

@ -1,4 +1,7 @@
<div class="top-row ps-3 navbar navbar-light"> @using TIAMWebApp.Shared.Application.Interfaces
@inject ISecureStorageHandler SecureStorageHandler
<div class="top-row ps-3 navbar navbar-light">
<div class="container-fluid"> <div class="container-fluid">
<button title="Back button" class="my-back-button" style="display:none" @onclick="NavigateBack"> <button title="Back button" class="my-back-button" style="display:none" @onclick="NavigateBack">
<img src="_content/TIAMSharedUI/images/navbar-toggler.png" width="40" /> <img src="_content/TIAMSharedUI/images/navbar-toggler.png" width="40" />
@ -44,8 +47,8 @@
</div> </div>
<hr /> <hr />
<div class="nav-item px-3"> <div class="nav-item px-3">
<NavLink class="nav-link" href="swagger"> <NavLink class="nav-link" href="#" @onclick="SignOut">
Api Signout
</NavLink> </NavLink>
</div> </div>
</nav> </nav>
@ -65,4 +68,9 @@
{ {
} }
private void SignOut()
{
SecureStorageHandler.ClearAllSecureStorageAsync();
}
} }

View File

@ -1,4 +1,7 @@
<div class="top-row ps-3 navbar navbar-light"> @using TIAMWebApp.Shared.Application.Interfaces
@inject ISecureStorageHandler SecureStorageHandler
<div class="top-row ps-3 navbar navbar-light">
<div class="container-fluid"> <div class="container-fluid">
<button title="Back button" class="my-back-button" style="display:none" @onclick="NavigateBack"> <button title="Back button" class="my-back-button" style="display:none" @onclick="NavigateBack">
<img src="_content/TIAMSharedUI/images/navbar-toggler.png" width="40" /> <img src="_content/TIAMSharedUI/images/navbar-toggler.png" width="40" />
@ -50,6 +53,11 @@
Settings Settings
</NavLink> </NavLink>
</div> </div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="#" @onclick="SignOut">
Signout
</NavLink>
</div>
</nav> </nav>
</div> </div>
@ -67,4 +75,10 @@
{ {
} }
private void SignOut()
{
SecureStorageHandler.ClearAllSecureStorageAsync();
}
} }

View File

@ -29,5 +29,17 @@ namespace TIAMWebApp.Client.Services
return await ssa.GetValueAsync<string>(key); return await ssa.GetValueAsync<string>(key);
} }
public async Task DeleteFromSecureStorageAsync(string key)
{
await localStoragService.RemoveItemAsync(key);
await ssa.RemoveAsync(key);
}
public async Task ClearAllSecureStorageAsync()
{
await localStoragService.ClearAsync();
await ssa.Clear();
}
} }
} }

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.JSInterop;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text; using System.Text;
@ -8,6 +9,7 @@ using TIAMWebApp.Shared.Application.Interfaces;
using TIAMWebApp.Shared.Application.Models; using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Models.ClientSide; using TIAMWebApp.Shared.Application.Models.ClientSide;
using TIAMWebApp.Shared.Application.Models.PageModels; using TIAMWebApp.Shared.Application.Models.PageModels;
using TIAMWebApp.Shared.Application.Utility;
namespace TIAMWebApp.Client.Services namespace TIAMWebApp.Client.Services
@ -16,13 +18,17 @@ namespace TIAMWebApp.Client.Services
{ {
private readonly HttpClient http; private readonly HttpClient http;
private readonly ISecureStorageHandler secureStorageHandler; private readonly ISecureStorageHandler secureStorageHandler;
private readonly IJSRuntime jsRuntime;
private readonly LogToBrowserConsole logToBrowserConsole;
public UserModel? User { get; set; } = new UserModel("", "", ""); public UserModel? User { get; set; } = new UserModel("", "", "");
public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public UserDataService(HttpClient http, ISecureStorageHandler secureStorageHandler) public UserDataService(HttpClient http, ISecureStorageHandler secureStorageHandler, IJSRuntime jSRuntime)
{ {
this.http = http; this.http = http;
this.secureStorageHandler = secureStorageHandler; this.secureStorageHandler = secureStorageHandler;
this.jsRuntime = jSRuntime;
this.logToBrowserConsole = new LogToBrowserConsole(jsRuntime);
} }
@ -109,8 +115,8 @@ namespace TIAMWebApp.Client.Services
bool isSuccess = true; bool isSuccess = true;
string result = string.Empty; string result = string.Empty;
var url = APIUrls.CreateUser; var url = $"{Setting.BaseUrl}/{APIUrls.CreateUser}";
logToBrowserConsole.LogToBC("CreateUser url: " + url);
var response = await http.PostAsJsonAsync(url, regModel); var response = await http.PostAsJsonAsync(url, regModel);
result = await response.Content.ReadAsStringAsync(); result = await response.Content.ReadAsStringAsync();
/*if (response.IsSuccessStatusCode) /*if (response.IsSuccessStatusCode)
@ -140,10 +146,12 @@ namespace TIAMWebApp.Client.Services
public async Task<bool> RefreshToken() public async Task<bool> RefreshToken()
{ {
logToBrowserConsole.LogToBC("RefreshToken() called");
bool isTokenRefreshed = false; bool isTokenRefreshed = false;
using (var client = new HttpClient()) using (var client = new HttpClient())
{ {
var url = APIUrls.RefreshToken; var url = $"{Setting.BaseUrl}{APIUrls.RefreshToken}";
//var url = APIUrls.RefreshToken;
var serializedStr = JsonConvert.SerializeObject(new AuthenticateRequestAndResponse var serializedStr = JsonConvert.SerializeObject(new AuthenticateRequestAndResponse
{ {
@ -153,6 +161,7 @@ namespace TIAMWebApp.Client.Services
try try
{ {
logToBrowserConsole.LogToBC("Refreshtoken url: " + url);
var response = await client.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json")); var response = await client.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@ -173,6 +182,7 @@ namespace TIAMWebApp.Client.Services
catch (Exception ex) catch (Exception ex)
{ {
string msg = ex.Message; string msg = ex.Message;
logToBrowserConsole.LogToBC("Refreshtoken exception: " + ex.ToString());
} }

View File

@ -16,7 +16,7 @@ using GoogleApi.Entities.Maps.DistanceMatrix.Response;
namespace TIAMWebApp.Server.Controllers namespace TIAMWebApp.Server.Controllers
{ {
[ApiController] [ApiController]
[Route("[controller]")] [Route("api/[controller]")]
public class GoogleAPIController : ControllerBase public class GoogleAPIController : ControllerBase
{ {

View File

@ -1,17 +1,22 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Text.Json;
using TIAM.Database.DataLayers; using TIAM.Database.DataLayers;
using TIAM.Database.DataLayers.TransferDestinations; using TIAM.Database.DataLayers.TransferDestinations;
using TIAM.Database.DataLayers.Users; using TIAM.Database.DataLayers.Users;
using TIAM.Database.DbContexts; using TIAM.Database.DbContexts;
using TIAM.Entities.TransferDestinations; using TIAM.Entities.TransferDestinations;
using TIAM.Entities.Users;
using TIAMWebApp.Shared.Application.Models; using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Models.PageModels;
namespace TIAMWebApp.Server.Controllers namespace TIAMWebApp.Server.Controllers
{ {
[ApiController] [ApiController]
[Route("[controller]")] [Route("api/[controller]")]
public class TransferDataAPIController : ControllerBase public class TransferDataAPIController : ControllerBase
{ {
//private static readonly TransferDestination[] Names = new TransferDestination[] //private static readonly TransferDestination[] Names = new TransferDestination[]
@ -28,18 +33,83 @@ namespace TIAMWebApp.Server.Controllers
//}; //};
private readonly TransferDestinationDal _transferDestinationDal; private readonly TransferDestinationDal _transferDestinationDal;
private readonly AdminDal _adminDal;
private readonly ILogger<TransferDataAPIController> _logger; private readonly ILogger<TransferDataAPIController> _logger;
public TransferDataAPIController(ILogger<TransferDataAPIController> logger, TransferDestinationDal transferDestinationDal) public TransferDataAPIController(ILogger<TransferDataAPIController> logger, TransferDestinationDal transferDestinationDal, AdminDal adminDal)
{ {
_logger = logger; _logger = logger;
_transferDestinationDal = transferDestinationDal; _transferDestinationDal = transferDestinationDal;
_adminDal = adminDal;
} }
[AllowAnonymous]
[HttpGet] [HttpGet]
public async Task<IEnumerable<TransferDestination>> Get() [Route("GetTransferDestinations")]
public async Task<IEnumerable<TransferDestination>> GetTransferDestinations()
{ {
return await _transferDestinationDal.Ctx.TransferDestinations.ToListAsync(); return await _transferDestinationDal.Ctx.TransferDestinations.ToListAsync();
} }
[AllowAnonymous]
[HttpGet]
[Route("GetTransferDestinationByCoordinates")]
public async Task<TransferDestination?> GetTransferDestinationByCoordinates(double latitude, double longitude)
{
return await _transferDestinationDal.Ctx.TransferDestinations.FirstOrDefaultAsync(x => x.Latitude == latitude && x.Longitude == longitude);
}
[AllowAnonymous]
[HttpGet]
[Route("GetTransferDestinationByAddress")]
public async Task<TransferDestination?> GetTransferDestinationByAddress(string address)
{
return await _transferDestinationDal.Ctx.TransferDestinations.FirstOrDefaultAsync(x => x.Address == address);
}
[AllowAnonymous]
[HttpPost]
[Route("CreateTransferDestination")]
public async Task<IActionResult> CreateTransferDestination([FromBody] JsonElement SerializedTransferDestinationModel)
{
Console.WriteLine("CreateTransferDestination called!");
if (string.IsNullOrEmpty(SerializedTransferDestinationModel.GetRawText()))
{
return BadRequest("SerializedLoginModel is required");
}
else
{
TransferDestination? transferDestination = JObject.Parse(SerializedTransferDestinationModel.GetRawText()).ToObject<TransferDestination>();
if (transferDestination != null)
{
var Id = Guid.NewGuid();
double Latitude = transferDestination.Latitude;
double Longitude = transferDestination.Longitude;
string Address = transferDestination.Address;
if (Id == null || Latitude == null || Longitude == null || Address == null)
{
return BadRequest("Invalid request");
}
else
{
Console.WriteLine($"TransferDestination to be created: {Id}");
Console.WriteLine($"TransferDestination to be created: {Latitude}");
Console.WriteLine($"TransferDestination to be created: {Longitude}");
Console.WriteLine($"TransferDestination to be created: {Address}");
await _transferDestinationDal.Ctx.TransferDestinations.AddRangeAsync(transferDestination);
}
}
return Ok("yes");
}
}
} }
} }

View File

@ -17,12 +17,14 @@ using System.Text;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using TIAM.Database.DataLayers.Users; using TIAM.Database.DataLayers.Users;
using AyCode.Utils.Helpers;
using TIAM.Entities.Users; using TIAM.Entities.Users;
using TIAMWebApp.Server.ModelsTIAMWebApp.Shared.Application.Models; using TIAMWebApp.Server.ModelsTIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Utility;
namespace TIAMWebApp.Server.Controllers namespace TIAMWebApp.Server.Controllers
{ {
//[Authorize] [Authorize]
[ApiController] [ApiController]
[Route("api/[controller]")] [Route("api/[controller]")]
public class UserAPIController : ControllerBase public class UserAPIController : ControllerBase
@ -83,61 +85,73 @@ namespace TIAMWebApp.Server.Controllers
}*/ }*/
[AllowAnonymous] [AllowAnonymous]
[HttpPost("AuthenticateUser")] [HttpPost]
[Route("AuthenticateUser")]
public async Task<IActionResult> AuthenticateUser([FromBody] JsonElement SerializedLoginModel) public async Task<IActionResult> AuthenticateUser([FromBody] JsonElement SerializedLoginModel)
{ {
Console.WriteLine("AuthenticateUser called");
var authenticateUser = JObject.Parse(SerializedLoginModel.GetRawText()).ToObject<LoginModel>(); var authenticateUser = JObject.Parse(SerializedLoginModel.GetRawText()).ToObject<LoginModel>();
//check if userModel exists //check if userModel exists
//var userModel = await _userManager.FindByNameAsync(authenticateUser.UserName); //var userModel = await _userManager.FindByNameAsync(authenticateUser.UserName);
//if (userModel == null) return Unauthorized(); //if (userModel == null) return Unauthorized();
Console.WriteLine(authenticateUser.Email);
var dbUser = await GetUserByEmail(authenticateUser.Email);
//mocking
var user = users.FirstOrDefault(x => x.Email == authenticateUser.Email);
//check if password is valid //check if password is valid
//bool isValidUser = await _userManager.CheckPasswordAsync(userModel, authenticateUser.Password); //bool isValidUser = await _userManager.CheckPasswordAsync(userModel, authenticateUser.Password);
//mocking //mocking
bool isValidUser = false; if (dbUser is null)
if (user.Password == authenticateUser.Password)
{
isValidUser = true;
}
if (isValidUser)
{
Console.WriteLine("UserModel authenticated, let's start JWT");
string accessToken = GenerateAccessToken(user);
Console.WriteLine("Generate refresh token");
var refreshToken = GenerateRefreshToken();
user.RefreshToken = refreshToken;
//Update userModel with refreshToken!!
//await _userManager.UpdateAsync(userModel);
var response = new MainResponse
{
Content = new AuthenticationResponse
{
RefreshToken = refreshToken,
AccessToken = accessToken
},
IsSuccess = true,
ErrorMessage = ""
};
return Ok(response);
}
else
{ {
return Unauthorized(); return Unauthorized();
} }
else
{
bool isValidUser = false;
if (dbUser.Password == authenticateUser.Password)
{
Console.WriteLine("Password is valid");
isValidUser = true;
}
if (isValidUser)
{
Console.WriteLine("UserModel authenticated, let's start JWT");
string accessToken = GenerateAccessToken(dbUser);
Console.WriteLine("Generate refresh token");
var refreshToken = GenerateRefreshToken();
dbUser.RefreshToken = refreshToken;
//Update userModel with refreshToken!!
await _userDal.UpdateUserAsync(dbUser);
var response = new MainResponse
{
Content = new AuthenticationResponse
{
RefreshToken = refreshToken,
AccessToken = accessToken
},
IsSuccess = true,
ErrorMessage = ""
};
return Ok(response);
}
else
{
return Unauthorized();
}
}
} }
private string GenerateAccessToken(UserModel userModel) private string GenerateAccessToken(User user)
{ {
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var token = new JwtSecurityToken(); var token = new JwtSecurityToken();
@ -147,8 +161,8 @@ namespace TIAMWebApp.Server.Controllers
var claims = new List<Claim> var claims = new List<Claim>
{ {
new Claim(ClaimTypes.NameIdentifier, userModel.Id.ToString()), new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, userModel.Email) new Claim(ClaimTypes.Email, user.Email)
}; };
var tokenDescriptor = new SecurityTokenDescriptor var tokenDescriptor = new SecurityTokenDescriptor
@ -166,12 +180,15 @@ namespace TIAMWebApp.Server.Controllers
} }
[AllowAnonymous] [AllowAnonymous]
[HttpPost("RefreshToken")] [HttpPost]
[Route("RefreshToken")]
public async Task<IActionResult> RefreshToken(RefreshTokenRequest refreshTokenRequest) public async Task<IActionResult> RefreshToken(RefreshTokenRequest refreshTokenRequest)
{ {
Console.WriteLine("RefreshToken called");
var response = new MainResponse(); var response = new MainResponse();
if (refreshTokenRequest is null) if (refreshTokenRequest is null)
{ {
Console.WriteLine("RefreshTokenRequest is null");
response.ErrorMessage = "Invalid request"; response.ErrorMessage = "Invalid request";
return BadRequest(response); return BadRequest(response);
} }
@ -180,23 +197,33 @@ namespace TIAMWebApp.Server.Controllers
if (principal != null) if (principal != null)
{ {
Console.WriteLine("Principal is not null");
var email = principal.Claims.FirstOrDefault(f => f.Type == ClaimTypes.Email); var email = principal.Claims.FirstOrDefault(f => f.Type == ClaimTypes.Email);
//var userModel = await _userManager.FindByEmailAsync(email?.Value); //var userModel = await _userManager.FindByEmailAsync(email?.Value);
var user = users.FirstOrDefault(x => x.Email == 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);
}
if (user is null || user.RefreshToken != refreshTokenRequest.RefreshToken) //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"; response.ErrorMessage = "Invalid Request";
return BadRequest(response); return BadRequest(response);
} }
string newAccessToken = GenerateAccessToken(user); string newAccessToken = GenerateAccessToken(dbUser);
string refreshToken = GenerateRefreshToken(); string refreshToken = GenerateRefreshToken();
//mocking - update userModel with new refreshToken //mocking - update userModel with new refreshToken
user.RefreshToken = refreshToken; dbUser.RefreshToken = refreshToken;
//await _userManager.UpdateAsync(userModel); //await _userManager.UpdateAsync(userModel);
response.IsSuccess = true; response.IsSuccess = true;
@ -209,6 +236,7 @@ namespace TIAMWebApp.Server.Controllers
} }
else else
{ {
Console.WriteLine("Principal is null");
return NotFound("Invalid Token Found"); return NotFound("Invalid Token Found");
} }
@ -251,29 +279,53 @@ namespace TIAMWebApp.Server.Controllers
} }
[AllowAnonymous]
[HttpPost] [HttpPost]
[Route("CreateUser")] [Route("CreateUser")]
public async Task<IActionResult> CreateUser([FromBody] JsonElement SerializedRegistrationModel) public async Task<IActionResult> CreateUser([FromBody] JsonElement SerializedRegistrationModel)
{ {
Console.WriteLine("CreateUser called");
if (string.IsNullOrEmpty(SerializedRegistrationModel.GetRawText())) if (string.IsNullOrEmpty(SerializedRegistrationModel.GetRawText()))
{ {
return BadRequest("SerializedLoginModel is required"); return BadRequest("SerializedLoginModel is required");
} }
else else
{ {
var user = JObject.Parse(SerializedRegistrationModel.GetRawText()).ToObject<RegistrationModel>(); RegistrationModel? user = JObject.Parse(SerializedRegistrationModel.GetRawText()).ToObject<RegistrationModel>();
if (users != null) if (users != null)
{ {
//add userModel to users array if(user != null)
Array.Resize(ref users, users.Length + 1); {
users[users.Length - 1] = new UserModel(user.Email, user.PhoneNumber, user.Password); //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();
string? email = user?.Email;
string? phoneNumber = user?.PhoneNumber;
string? password = user?.Password;
if(email is null || phoneNumber is null || password is null)
{
return BadRequest("Invalid request");
}
else
{
Console.WriteLine($"User to be created: {userId}");
Console.WriteLine($"User to be created: {email}");
Console.WriteLine($"User to be created: {phoneNumber}");
Console.WriteLine($"User to be created: {password}");
await _userDal.CreateUserAsync(new User(userId, email, phoneNumber, password));
}
}
return Ok("yes"); return Ok("yes");
} }
else else
{ {
return Ok("no"); return NotFound("no");
} }
} }
@ -296,21 +348,22 @@ namespace TIAMWebApp.Server.Controllers
} }
[AllowAnonymous]
[HttpGet] [HttpGet]
[Route("GetUsers")] [Route("GetUsers")]
public Task<List<User?>> GetUsers() public Task<List<User>> GetUsers()
{ {
//var users = await _userDal.Ctx.Users.ToListAsync();//.GetUsersAsync(); //var users = await _userDal.Ctx.Users.ToListAsync();//.GetUsersAsync();
//return users; //return users;
return _userDal.GetUsersAsync(); return _userDal.GetUsersAsync();
} }
[AllowAnonymous]
[HttpGet] [HttpGet]
[Route("GetUserByEmail")] [Route("GetUserByEmail")]
public Task<User?> GetUserByEmail(string email) public async Task<User?> GetUserByEmail(string email)
{ {
return _userDal.GetUserByEmailAsync(email); return await _userDal.GetUserByEmailAsync(email);
} }
private bool VerifyPassword(string password, string hashedPassword) private bool VerifyPassword(string password, string hashedPassword)

View File

@ -4,7 +4,7 @@ using TIAMWebApp.Shared.Application.Models;
namespace TIAMWebApp.Server.Controllers namespace TIAMWebApp.Server.Controllers
{ {
[ApiController] [ApiController]
[Route("[controller]")] [Route("api/[controller]")]
public class WeatherForecastAPIController : ControllerBase public class WeatherForecastAPIController : ControllerBase
{ {
private static readonly string[] Summaries = new[] private static readonly string[] Summaries = new[]

View File

@ -21,7 +21,7 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
//builder.Services.AddDbContext<TransferDestinationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DeveloperDbConnection")));; //builder.Services.AddDbContext<TransferDestinationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DeveloperDbConnection")));;
builder.Services.AddScoped<UserDal>(); builder.Services.AddScoped<AdminDal>();
builder.Services.AddScoped<TransferDestinationDal>(); builder.Services.AddScoped<TransferDestinationDal>();
builder.Services.AddSwaggerGen(swagger => builder.Services.AddSwaggerGen(swagger =>

View File

@ -47,6 +47,9 @@
<Reference Include="AyCode.Interfaces.Server"> <Reference Include="AyCode.Interfaces.Server">
<HintPath>..\..\..\AyCode.Core\AyCode.Database\bin\Debug\net7.0\AyCode.Interfaces.Server.dll</HintPath> <HintPath>..\..\..\AyCode.Core\AyCode.Database\bin\Debug\net7.0\AyCode.Interfaces.Server.dll</HintPath>
</Reference> </Reference>
<Reference Include="AyCode.Utils">
<HintPath>..\..\..\AyCode.Core\AyCode.Utils\bin\Debug\net7.0\AyCode.Utils.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>

View File

@ -10,5 +10,8 @@ namespace TIAMWebApp.Shared.Application.Interfaces
{ {
public Task SaveToSecureStorageAsync(string key, string value); public Task SaveToSecureStorageAsync(string key, string value);
public Task<string> GetFromSecureStorageAsync(string key); public Task<string> GetFromSecureStorageAsync(string key);
public Task DeleteFromSecureStorageAsync(string key);
public Task ClearAllSecureStorageAsync();
} }
} }

View File

@ -13,8 +13,9 @@ namespace TIAMWebApp.Shared.Application.Models
public const string GetUsers = "api/UserAPI/GetUsers"; public const string GetUsers = "api/UserAPI/GetUsers";
public const string AuthenticateUser = "api/UserAPI/AuthenticateUser"; public const string AuthenticateUser = "api/UserAPI/AuthenticateUser";
public const string CreateUser = "api/UserAPI/CreateUser"; public const string CreateUser = "api/UserAPI/CreateUser";
public const string RefreshToken = "api/UserAPI/RefreshToken"; public const string RefreshToken = "/api/UserAPI/RefreshToken";
public const string WeatherForecast = "WeatherForecastAPI"; public const string WeatherForecast = "api/WeatherForecastAPI";
public const string PopulationStructure = "PopulationStructureAPI"; public const string PopulationStructure = "PopulationStructureAPI";
public const string GetTransferDestinations = "api/GetTransferDestinations";
} }
} }

View File

@ -9,5 +9,6 @@ namespace TIAMWebApp.Shared.Application.Models.ClientSide
public class Setting public class Setting
{ {
public static UserBasicDetails UserBasicDetails { get; set; } public static UserBasicDetails UserBasicDetails { get; set; }
public const string BaseUrl = "https://localhost:7116";
} }
} }

View File

@ -4,7 +4,12 @@ namespace TIAMWebApp.Shared.Application.Utility
{ {
public class LogToBrowserConsole public class LogToBrowserConsole
{ {
private readonly JSRuntime jsRuntime; private readonly IJSRuntime jsRuntime;
public LogToBrowserConsole(IJSRuntime jsRuntime)
{
this.jsRuntime = jsRuntime;
}
public void LogToBC(string message) public void LogToBC(string message)
{ {

View File

@ -1,48 +0,0 @@
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.Security.Cryptography;
public class PasswordHasher
{
public string HashPassword(string password)
{
// Generate a random salt
byte[] salt = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
// Hash the password with the salt
string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA512,
iterationCount: 10000,
numBytesRequested: 32));
// Combine the salt and hashed password
string combinedHash = $"$bcrypt$v=1$salt={Convert.ToBase64String(salt)}$hash={hashedPassword}";
return combinedHash;
}
public bool VerifyPassword(string password, string hashedPassword)
{
// Extract the salt and hashed password from the combined hash
string[] parts = hashedPassword.Split('$');
byte[] salt = Convert.FromBase64String(parts[3]);
string storedHash = parts[5];
// Hash the provided password with the extracted salt
string hashedProvidedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA512,
iterationCount: 10000,
numBytesRequested: 32));
// Compare the hashed passwords
return storedHash == hashedProvidedPassword;
}
}