merge
This commit is contained in:
commit
4ba61ba048
|
|
@ -3,6 +3,7 @@ using TIAMMobileApp.Services;
|
|||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using DevExpress.Blazor;
|
||||
using TIAMMobilApp.Services;
|
||||
using TIAMWebApp.Shared.Application.Utility;
|
||||
|
||||
namespace TIAMMobileApp
|
||||
{
|
||||
|
|
@ -35,7 +36,7 @@ namespace TIAMMobileApp
|
|||
/*Android*/
|
||||
//client.BaseAddress = new Uri("https://10.0.2.2:7116");
|
||||
|
||||
builder.Services.AddScoped(sp => client);
|
||||
builder.Services.AddSingleton(sp => client);
|
||||
|
||||
builder.Services.AddDevExpressBlazor(configure => configure.BootstrapVersion = BootstrapVersion.v5);
|
||||
|
||||
|
|
@ -43,7 +44,9 @@ namespace TIAMMobileApp
|
|||
builder.Services.AddScoped<ITransferDataService, TransferDataService>();
|
||||
builder.Services.AddScoped<IPopulationStructureDataProvider, PopulationStructureDataProvider>();
|
||||
builder.Services.AddScoped<ISupplierService, SupplierService>();
|
||||
builder.Services.AddSingleton<IUserDataService, UserDataService>();
|
||||
builder.Services.AddScoped<IUserDataService, UserDataService>();
|
||||
builder.Services.AddScoped<ISecureStorageHandler, SecureStorageHandler>();
|
||||
builder.Services.AddScoped<LogToBrowserConsole>();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||||
|
||||
namespace TIAMMobileApp.Services
|
||||
{
|
||||
public class SecureStorageHandler : ISecureStorageHandler
|
||||
{
|
||||
public async Task SaveToSecureStorageAsync(string key, string value)
|
||||
{
|
||||
|
||||
await SecureStorage.SetAsync(key, value);
|
||||
|
||||
}
|
||||
|
||||
public async Task<string> GetFromSecureStorageAsync(string key)
|
||||
{
|
||||
return await SecureStorage.GetAsync(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using System.Net.Http.Json;
|
|||
using System.Text;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||||
using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
|
||||
|
||||
|
|
@ -12,12 +13,14 @@ namespace TIAMMobilApp.Services
|
|||
public class UserDataService : IUserDataService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
public User? User { get; set; } = new User("","","");
|
||||
private readonly ISecureStorageHandler secureStorageHandler;
|
||||
public User? User { get; set; } = new User("", "", "");
|
||||
public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public UserDataService(HttpClient http)
|
||||
public UserDataService(HttpClient http, ISecureStorageHandler secureStorageHandler)
|
||||
{
|
||||
this.http = http;
|
||||
this.secureStorageHandler = secureStorageHandler;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -40,7 +43,7 @@ namespace TIAMMobilApp.Services
|
|||
{
|
||||
if (User == null)
|
||||
{
|
||||
User = new User("","","");
|
||||
User = new User("", "", "");
|
||||
User.IsLoggedIn = false;
|
||||
User.UserType = UserType.User;
|
||||
return User;
|
||||
|
|
@ -50,7 +53,7 @@ namespace TIAMMobilApp.Services
|
|||
{
|
||||
return User;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Mock method for now
|
||||
|
|
@ -66,7 +69,8 @@ namespace TIAMMobilApp.Services
|
|||
return User;
|
||||
}
|
||||
|
||||
public async Task<string> TestUserApi(int Param) {
|
||||
public async Task<string> TestUserApi(int Param)
|
||||
{
|
||||
var url = APIUrls.UserTest;
|
||||
var response = await http.PostAsJsonAsync(url, Param);
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
|
|
@ -75,15 +79,15 @@ namespace TIAMMobilApp.Services
|
|||
|
||||
public async Task<string> AuthenticateUser(LoginModel loginModel)
|
||||
{
|
||||
|
||||
|
||||
|
||||
string result = string.Empty;
|
||||
var url = APIUrls.AuthenticateUser;
|
||||
|
||||
|
||||
|
||||
string result = string.Empty;
|
||||
var url = APIUrls.AuthenticateUser;
|
||||
|
||||
var response = await http.PostAsJsonAsync(url, loginModel);
|
||||
|
||||
if(response.IsSuccessStatusCode)
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
result = await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
|
@ -95,7 +99,7 @@ namespace TIAMMobilApp.Services
|
|||
//result = await response.Content.ReadAsStringAsync();
|
||||
return result;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async Task<(bool isSuccess, string ErrorMessage)> CreateUser(RegistrationModel regModel)
|
||||
|
|
@ -105,7 +109,7 @@ namespace TIAMMobilApp.Services
|
|||
string result = string.Empty;
|
||||
var url = APIUrls.CreateUser;
|
||||
|
||||
var response = await http.PostAsJsonAsync(url, regModel);
|
||||
var response = await http.PostAsJsonAsync(url, regModel);
|
||||
result = await response.Content.ReadAsStringAsync();
|
||||
/*if (response.IsSuccessStatusCode)
|
||||
{
|
||||
|
|
@ -122,25 +126,67 @@ namespace TIAMMobilApp.Services
|
|||
return (isSuccess, result);
|
||||
}
|
||||
|
||||
public async Task<bool> RefreshToken()
|
||||
{
|
||||
bool isTokenRefreshed = false;
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var url = APIUrls.RefreshToken;
|
||||
|
||||
var serializedStr = JsonConvert.SerializeObject(new AuthenticateRequestAndResponse
|
||||
{
|
||||
RefreshToken = Setting.UserBasicDetails.RefreshToken,
|
||||
AccessToken = Setting.UserBasicDetails.AccessToken
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
string contentStr = await response.Content.ReadAsStringAsync();
|
||||
var mainResponse = JsonConvert.DeserializeObject<MainResponse>(contentStr);
|
||||
if (mainResponse.IsSuccess)
|
||||
{
|
||||
var tokenDetails = JsonConvert.DeserializeObject<AuthenticateRequestAndResponse>(mainResponse.Content.ToString());
|
||||
Setting.UserBasicDetails.AccessToken = tokenDetails.AccessToken;
|
||||
Setting.UserBasicDetails.RefreshToken = tokenDetails.RefreshToken;
|
||||
|
||||
string userDetailsStr = JsonConvert.SerializeObject(Setting.UserBasicDetails);
|
||||
await secureStorageHandler.SaveToSecureStorageAsync(nameof(Setting.UserBasicDetails), userDetailsStr);
|
||||
isTokenRefreshed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = ex.Message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return isTokenRefreshed;
|
||||
}
|
||||
|
||||
|
||||
public Task<Dictionary<int, string>> GetUserRolesAsync(User user)
|
||||
{
|
||||
|
||||
//get the user's roles
|
||||
int role = User.UserRoles;
|
||||
int role = User.UserRoles;
|
||||
|
||||
foreach (var roleType in roleTypes)
|
||||
foreach (var roleType in roleTypes)
|
||||
{
|
||||
if ((role & roleType.Id) == roleType.Id)
|
||||
{
|
||||
if ((role & roleType.Id) == roleType.Id)
|
||||
{
|
||||
|
||||
//add the role to the dictionary
|
||||
userRoleTypes.Add(roleType.Id, roleType.RoleName);
|
||||
|
||||
}
|
||||
//add the role to the dictionary
|
||||
userRoleTypes.Add(roleType.Id, roleType.RoleName);
|
||||
|
||||
}
|
||||
}
|
||||
return Task.FromResult(userRoleTypes);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
@page "/";
|
||||
@using TIAMWebApp.Shared.Application.Interfaces
|
||||
@using TIAMWebApp.Shared.Application.Models
|
||||
@using TIAMWebApp.Shared.Application.Utility
|
||||
@using Newtonsoft.Json
|
||||
@using System.IdentityModel.Tokens.Jwt
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide
|
||||
@inject NavigationManager NavManager
|
||||
@inject LogToBrowserConsole logToBrowserConsole
|
||||
@inject IUserDataService UserDataService
|
||||
@inject ISecureStorageHandler SecureStorageHandler
|
||||
<h3>AppLaunch</h3>
|
||||
|
||||
Loading....
|
||||
|
||||
@code {
|
||||
|
||||
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
string userDetailsStr = await SecureStorageHandler.GetFromSecureStorageAsync(nameof(Setting.UserBasicDetails));
|
||||
logToBrowserConsole.LogToBC(userDetailsStr);
|
||||
if (!string.IsNullOrWhiteSpace(userDetailsStr))
|
||||
{
|
||||
var userBasicDetail = JsonConvert.DeserializeObject<UserBasicDetails>(userDetailsStr);
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jsontoken = handler.ReadToken(userBasicDetail.AccessToken) as JwtSecurityToken;
|
||||
Setting.UserBasicDetails = userBasicDetail;
|
||||
|
||||
if (jsontoken.ValidTo < DateTime.UtcNow)
|
||||
{
|
||||
bool isTokenRefreshed = await UserDataService.RefreshToken();
|
||||
|
||||
if (isTokenRefreshed)
|
||||
{
|
||||
NavManager.NavigateTo("/home");
|
||||
}
|
||||
else
|
||||
{
|
||||
NavManager.NavigateTo("/login");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
NavManager.NavigateTo("/home");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NavManager.NavigateTo("/login");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
Mask="\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*\d\W*(\d{1,2})"
|
||||
MaskMode="@MaskMode.RegEx">
|
||||
<DxRegExMaskProperties Placeholder="Placeholder"
|
||||
PlaceholdersVisible=false/>
|
||||
PlaceholdersVisible=true/>
|
||||
</DxMaskedInput>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@page "/"
|
||||
@page "/index"
|
||||
@using TIAMSharedUI.Shared
|
||||
|
||||
<PageTitle>Index</PageTitle>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@page "/login"
|
||||
@page "/login_old"
|
||||
@using TIAMWebApp.Shared.Application.Interfaces;
|
||||
@using TIAMWebApp.Shared.Application.Models;
|
||||
@using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
@page "/login2"
|
||||
@page "/login"
|
||||
@using System.IdentityModel.Tokens.Jwt;
|
||||
@using System.Security.Claims;
|
||||
@using Newtonsoft.Json.Linq;
|
||||
@using System.Text.Json;
|
||||
@using System.Reflection;
|
||||
@using TIAMWebApp.Shared.Application.Interfaces;
|
||||
@using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
@using TIAMSharedUI.Pages.Components;
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||||
@using TIAMWebApp.Shared.Application.Models;
|
||||
@using TIAMWebApp.Shared.Application.Utility;
|
||||
@inject NavigationManager navManager
|
||||
@inject LogToBrowserConsole logToBrowserConsole
|
||||
@inject IUserDataService UserDataservice
|
||||
@inject IJSRuntime jsRuntime
|
||||
@inject ISecureStorageHandler SecureStorageHandler
|
||||
|
||||
<PageTitle>Login</PageTitle>
|
||||
|
||||
|
|
@ -54,11 +64,11 @@
|
|||
@code {
|
||||
|
||||
LoginModel loginModel = new();
|
||||
|
||||
|
||||
private int currentStep = 1;
|
||||
|
||||
bool loggedIn = false;
|
||||
|
||||
|
||||
|
||||
private void GoToNextStep()
|
||||
{
|
||||
|
|
@ -73,58 +83,80 @@
|
|||
private async void SubmitLogin()
|
||||
{
|
||||
|
||||
// Implement your registration logic here
|
||||
// You can use Email, PhoneNumber, and Password variables
|
||||
// Reset currentStep after successful registration
|
||||
loggedIn = true;
|
||||
|
||||
currentStep = 1;
|
||||
LogToBrowserConsole("Login started: " + "Email: " + loginModel.Email + ", Password: " + loginModel.Password);
|
||||
logToBrowserConsole.LogToBC("Login started: " + "Email: " + loginModel.Email + ", Password: " + loginModel.Password);
|
||||
var response = await UserDataservice.AuthenticateUser(loginModel);
|
||||
//var response = await UserDataservice.TestUserApi(30);
|
||||
LogToBrowserConsole("Login started");
|
||||
|
||||
logToBrowserConsole.LogToBC("Login started");
|
||||
logToBrowserConsole.LogToBC(response);
|
||||
if (!string.IsNullOrEmpty(response))
|
||||
{
|
||||
LogToBrowserConsole(response);
|
||||
if (response == "no")
|
||||
//get token and save to local storage
|
||||
//parse to Mainresponse from json string
|
||||
|
||||
|
||||
//var Mainresponse = JsonSerializer.Deserialize<MainResponse>(response);
|
||||
var Mainresponse = JsonSerializer.Deserialize<MainResponse>(response, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
if (Mainresponse != null)
|
||||
{
|
||||
//await App.Current.MainPage.DisplayAlert("Error", "Invalid credentials", "Ok");
|
||||
//display error message via jsinterop
|
||||
LogToBrowserConsole("Invalid credentials");
|
||||
navManager.NavigateTo("login2");
|
||||
|
||||
//check for bad request
|
||||
|
||||
string AuthResponseJson = JsonSerializer.Serialize(Mainresponse.Content);
|
||||
|
||||
var AuthResponse = JsonSerializer.Deserialize<AuthenticationResponse>(AuthResponseJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
string accessToken = AuthResponse.AccessToken;
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var token = handler.ReadJwtToken(accessToken) as JwtSecurityToken;
|
||||
|
||||
string _userId = token.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value;
|
||||
string _email = token.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.Email).Value;
|
||||
|
||||
var userBasicDetails = new UserBasicDetails(_userId, _email, AuthResponse.AccessToken, AuthResponse.RefreshToken);
|
||||
|
||||
string userBasicDetailsJson = JsonSerializer.Serialize(userBasicDetails);
|
||||
|
||||
|
||||
//save to local storage
|
||||
await SecureStorageHandler.SaveToSecureStorageAsync(nameof(Setting.UserBasicDetails), userBasicDetailsJson);
|
||||
|
||||
|
||||
if (!Mainresponse.IsSuccess)
|
||||
{
|
||||
//await App.Current.MainPage.DisplayAlert("Error", "Invalid credentials", "Ok");
|
||||
//display error message via jsinterop
|
||||
logToBrowserConsole.LogToBC("Invalid credentials");
|
||||
navManager.NavigateTo("login2");
|
||||
}
|
||||
else
|
||||
{
|
||||
//await App.Current.MainPage.DisplayAlert("Success", "Successful login", "Ok");
|
||||
//display success message via jsinterop
|
||||
logToBrowserConsole.LogToBC("Successful login");
|
||||
var user = await UserDataservice.IsLoggedInAsync();
|
||||
user.IsLoggedIn = true;
|
||||
|
||||
user.UserType = UserType.Admin;
|
||||
navManager.NavigateTo("home");
|
||||
}
|
||||
|
||||
}
|
||||
else if(response == "yes")
|
||||
{
|
||||
//await App.Current.MainPage.DisplayAlert("Success", "Successful login", "Ok");
|
||||
//display success message via jsinterop
|
||||
LogToBrowserConsole("Successful login");
|
||||
navManager.NavigateTo("home");
|
||||
}
|
||||
else
|
||||
{
|
||||
//await App.Current.MainPage.DisplayAlert("Error", "An error occured while trying to login", "Ok");
|
||||
//display error message via jsinterop
|
||||
LogToBrowserConsole("An error occured while trying to login");
|
||||
navManager.NavigateTo("login2");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//api error
|
||||
//await App.Current.MainPage.DisplayAlert("Error", "An error occured while trying to login", "Ok");
|
||||
//display error message via jsinterop
|
||||
LogToBrowserConsole("An error occured while trying to login");
|
||||
logToBrowserConsole.LogToBC("An error occured while trying to login");
|
||||
navManager.NavigateTo("login2");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void LogToBrowserConsole(string message)
|
||||
{
|
||||
jsRuntime.InvokeVoidAsync("console.log", message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
@page "/register2"
|
||||
@inject NavigationManager navManager;
|
||||
<PageTitle>Register step 2</PageTitle>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="my-logo">
|
||||
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
|
||||
</div>
|
||||
<div class="text-center mt-4 name">
|
||||
Let's create your account!
|
||||
</div>
|
||||
<form class="p-3 mt-3">
|
||||
<div class="form-field d-flex align-items-center">
|
||||
<span class="fas fa-key"></span>
|
||||
<input type="password" name="password" id="pwd" placeholder="Password">
|
||||
</div>
|
||||
|
||||
<a class="btn btn-secondary mt-3" @onclick="back">Previous</a>
|
||||
<a class="btn btn-primary mt-3" @onclick="next">Next</a>
|
||||
</form>
|
||||
<div class="text-center fs-6">
|
||||
Already have an account? <a href="login">Sign in here!</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private void next()
|
||||
{
|
||||
navManager.NavigateTo("register3");
|
||||
}
|
||||
private void back()
|
||||
{
|
||||
navManager.NavigateTo("register");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
.wrapper {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
@page "/register3"
|
||||
@inject NavigationManager navManager;
|
||||
<PageTitle>Register step 3</PageTitle>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="my-logo">
|
||||
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
|
||||
</div>
|
||||
<div class="text-center mt-4 name">
|
||||
Let's create your account!
|
||||
</div>
|
||||
<form class="p-3 mt-3">
|
||||
<div class="form-field d-flex align-items-center">
|
||||
<span class="fas fa-key"></span>
|
||||
<input type="password" name="password" id="pwd" placeholder="Confirm password">
|
||||
</div>
|
||||
|
||||
<a class="btn btn-secondary mt-3" @onclick="back">Previous</a>
|
||||
<a class="btn btn-primary mt-3" @onclick="next">Next</a>
|
||||
</form>
|
||||
<div class="text-center fs-6">
|
||||
Already have an account? <a href="login">Sign in here!</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private void next()
|
||||
{
|
||||
navManager.NavigateTo("register4");
|
||||
}
|
||||
private void back()
|
||||
{
|
||||
navManager.NavigateTo("register2");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
.wrapper {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
@page "/register4"
|
||||
@inject NavigationManager navManager;
|
||||
<PageTitle>Register step 4</PageTitle>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="my-logo">
|
||||
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
|
||||
</div>
|
||||
<div class="text-center mt-4 name">
|
||||
Let's create your account!
|
||||
</div>
|
||||
<form class="p-3 mt-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1" checked>
|
||||
<label class="form-check-label" for="flexRadioDefault1">
|
||||
Customer
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2" disabled>
|
||||
<label class="form-check-label" for="flexRadioDefault2">
|
||||
Service provider (not available yet)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" value="" id="flexCheckDefault">
|
||||
<label class="form-check-label" for="flexCheckDefault">
|
||||
I accept the <a href="terms">Terms and Conditions</a> of use.
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<a class="btn btn-secondary mt-3" @onclick="back">Previous</a>
|
||||
<a class="btn btn-primary mt-3" @onclick="next">Next</a>
|
||||
</form>
|
||||
<div class="text-center fs-6">
|
||||
Already have an account? <a href="login">Sign in here!</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private void next()
|
||||
{
|
||||
navManager.NavigateTo("login");
|
||||
}
|
||||
private void back()
|
||||
{
|
||||
navManager.NavigateTo("register3");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
.wrapper {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
label {
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.card-input-element + .card {
|
||||
height: calc(36px + 2*1rem);
|
||||
color: var(--primary);
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.card-input-element + .card:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-input-element:checked + .card {
|
||||
border: 2px solid var(--primary);
|
||||
-webkit-transition: border .3s;
|
||||
-o-transition: border .3s;
|
||||
transition: border .3s;
|
||||
}
|
||||
|
||||
.card-input-element:checked + .card::after {
|
||||
content: '\e5ca';
|
||||
color: #AFB8EA;
|
||||
font-family: 'Material Icons';
|
||||
font-size: 24px;
|
||||
-webkit-animation-name: fadeInCheckbox;
|
||||
animation-name: fadeInCheckbox;
|
||||
-webkit-animation-duration: .5s;
|
||||
animation-duration: .5s;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeInCheckbox {
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: rotateZ(-20deg);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
-webkit-transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInCheckbox {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: rotateZ(-20deg);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,12 +14,9 @@
|
|||
|
||||
|
||||
<article class="content">
|
||||
@{
|
||||
if (isUserLoggedIn)
|
||||
{
|
||||
<TopRow></TopRow>
|
||||
}
|
||||
}
|
||||
|
||||
<TopRow></TopRow>
|
||||
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
|
|
@ -27,7 +24,7 @@
|
|||
|
||||
@code {
|
||||
|
||||
bool isUserLoggedIn;
|
||||
/*bool isUserLoggedIn;
|
||||
int userType = 0;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
|
|
@ -39,5 +36,5 @@
|
|||
{
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
@inherits LayoutComponentBase
|
||||
@using TIAMWebApp.Shared.Application.Interfaces
|
||||
@using TIAMSharedUI.Pages
|
||||
@using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||||
@inject IUserDataService UserDataService;
|
||||
@inject IJSRuntime jsRuntime
|
||||
|
||||
<div class="page">
|
||||
<div class="my-sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
@if (Setting.UserBasicDetails != null)
|
||||
{
|
||||
<div class="my-sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<main>
|
||||
|
||||
@* <ChooseDestination>
|
||||
</ChooseDestination>
|
||||
*@
|
||||
|
||||
<article class="content">
|
||||
@{
|
||||
if(isUserLoggedIn)
|
||||
|
|
@ -46,16 +48,13 @@
|
|||
|
||||
protected override void OnAfterRender(bool isFirst)
|
||||
{
|
||||
LogToBrowserConsole("0 ");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void LogToBrowserConsole(string message)
|
||||
{
|
||||
jsRuntime.InvokeVoidAsync("console.log", message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,9 @@
|
|||
<NavLink class="nav-link" href="counter">
|
||||
Counter
|
||||
</NavLink>
|
||||
</div>
|
||||
<div-- class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
Fetch data
|
||||
</NavLink>
|
||||
</div-->
|
||||
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="transfer">
|
||||
Transfer
|
||||
|
|
@ -45,6 +42,12 @@
|
|||
Login
|
||||
</NavLink>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="swagger">
|
||||
Api
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
using Blazored.LocalStorage;
|
||||
using DevExpress.Blazor;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Microsoft.JSInterop;
|
||||
using TIAMWebApp.Client;
|
||||
using TIAMWebApp.Client.Services;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using TIAMWebApp.Shared.Application.Utility;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
|
|
@ -13,7 +16,15 @@ builder.Services.AddScoped<IWeatherForecastService, WeatherForecastService>();
|
|||
builder.Services.AddScoped<ITransferDataService, TransferDataService>();
|
||||
builder.Services.AddScoped<IPopulationStructureDataProvider, PopulationStructureDataProvider>();
|
||||
builder.Services.AddScoped<ISupplierService, SupplierService>();
|
||||
builder.Services.AddSingleton<IUserDataService, UserDataService>();
|
||||
builder.Services.AddScoped<IUserDataService, UserDataService>();
|
||||
builder.Services.AddScoped<ISecureStorageHandler, SecureStorageHandler>();
|
||||
builder.Services.AddScoped<LogToBrowserConsole>();
|
||||
builder.Services.AddBlazoredLocalStorage();
|
||||
//WebSpecific
|
||||
builder.Services.AddScoped<SessionStorageAccessor>();
|
||||
//WebSpecific end
|
||||
|
||||
|
||||
builder.Services.AddSingleton(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||
builder.Services.AddDevExpressBlazor(configure => configure.BootstrapVersion = BootstrapVersion.v5);
|
||||
await builder.Build().RunAsync();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
using Microsoft.JSInterop;
|
||||
|
||||
namespace TIAMWebApp.Client.Services
|
||||
{
|
||||
public class LocalStorageAccessor : IAsyncDisposable
|
||||
{
|
||||
private Lazy<IJSObjectReference> _accessorJsRef = new();
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public LocalStorageAccessor(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
private async Task WaitForReference()
|
||||
{
|
||||
if (_accessorJsRef.IsValueCreated is false)
|
||||
{
|
||||
_accessorJsRef = new(await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "/js/LocalStorageAccessor.js"));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_accessorJsRef.IsValueCreated)
|
||||
{
|
||||
await _accessorJsRef.Value.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using Blazored.LocalStorage;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
|
||||
namespace TIAMWebApp.Client.Services
|
||||
{
|
||||
public class SecureStorageHandler : ISecureStorageHandler
|
||||
{
|
||||
private readonly SessionStorageAccessor ssa;
|
||||
private readonly ILocalStorageService localStoragService;
|
||||
|
||||
public SecureStorageHandler(SessionStorageAccessor ssa, ILocalStorageService localStorageService)
|
||||
{
|
||||
this.ssa = ssa;
|
||||
this.localStoragService = localStorageService;
|
||||
}
|
||||
|
||||
|
||||
public async Task SaveToSecureStorageAsync(string key, string value)
|
||||
{
|
||||
await localStoragService.SetItemAsync(key, value);
|
||||
await ssa.SetValueAsync(key, value);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async Task<string> GetFromSecureStorageAsync(string key)
|
||||
{
|
||||
return await localStoragService.GetItemAsync<string>(key);
|
||||
return await ssa.GetValueAsync<string>(key);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using Microsoft.JSInterop;
|
||||
|
||||
namespace TIAMWebApp.Client.Services
|
||||
{
|
||||
public class SessionStorageAccessor : IAsyncDisposable
|
||||
{
|
||||
private Lazy<IJSObjectReference> _accessorJsRef = new();
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public SessionStorageAccessor(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
private async Task WaitForReference()
|
||||
{
|
||||
if (_accessorJsRef.IsValueCreated is false)
|
||||
{
|
||||
_accessorJsRef = new(await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "/js/SessionStorageAccessor.js"));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_accessorJsRef.IsValueCreated)
|
||||
{
|
||||
await _accessorJsRef.Value.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<T> GetValueAsync<T>(string key)
|
||||
{
|
||||
await WaitForReference();
|
||||
var result = await _accessorJsRef.Value.InvokeAsync<T>("get", key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task SetValueAsync<T>(string key, T value)
|
||||
{
|
||||
await WaitForReference();
|
||||
await _accessorJsRef.Value.InvokeVoidAsync("set", key, value);
|
||||
}
|
||||
|
||||
public async Task Clear()
|
||||
{
|
||||
await WaitForReference();
|
||||
await _accessorJsRef.Value.InvokeVoidAsync("clear");
|
||||
}
|
||||
|
||||
public async Task RemoveAsync(string key)
|
||||
{
|
||||
await WaitForReference();
|
||||
await _accessorJsRef.Value.InvokeVoidAsync("remove", key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using System.Net.Http.Json;
|
|||
using System.Text;
|
||||
using TIAMWebApp.Shared.Application.Interfaces;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
using TIAMWebApp.Shared.Application.Models.ClientSide;
|
||||
using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
|
||||
|
||||
|
|
@ -12,12 +13,14 @@ namespace TIAMWebApp.Client.Services
|
|||
public class UserDataService : IUserDataService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
public User? User { get; set; } = new User("","","");
|
||||
private readonly ISecureStorageHandler secureStorageHandler;
|
||||
public User? User { get; set; } = new User("", "", "");
|
||||
public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public UserDataService(HttpClient http)
|
||||
public UserDataService(HttpClient http, ISecureStorageHandler secureStorageHandler)
|
||||
{
|
||||
this.http = http;
|
||||
this.secureStorageHandler = secureStorageHandler;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -40,7 +43,7 @@ namespace TIAMWebApp.Client.Services
|
|||
{
|
||||
if (User == null)
|
||||
{
|
||||
User = new User("","","");
|
||||
User = new User("", "", "");
|
||||
User.IsLoggedIn = false;
|
||||
User.UserType = UserType.User;
|
||||
return User;
|
||||
|
|
@ -50,7 +53,7 @@ namespace TIAMWebApp.Client.Services
|
|||
{
|
||||
return User;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Mock method for now
|
||||
|
|
@ -66,7 +69,8 @@ namespace TIAMWebApp.Client.Services
|
|||
return User;
|
||||
}
|
||||
|
||||
public async Task<string> TestUserApi(int Param) {
|
||||
public async Task<string> TestUserApi(int Param)
|
||||
{
|
||||
var url = APIUrls.UserTest;
|
||||
var response = await http.PostAsJsonAsync(url, Param);
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
|
|
@ -75,15 +79,15 @@ namespace TIAMWebApp.Client.Services
|
|||
|
||||
public async Task<string> AuthenticateUser(LoginModel loginModel)
|
||||
{
|
||||
|
||||
|
||||
|
||||
string result = string.Empty;
|
||||
var url = APIUrls.AuthenticateUser;
|
||||
|
||||
|
||||
|
||||
string result = string.Empty;
|
||||
var url = APIUrls.AuthenticateUser;
|
||||
|
||||
var response = await http.PostAsJsonAsync(url, loginModel);
|
||||
|
||||
if(response.IsSuccessStatusCode)
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
result = await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
|
@ -95,7 +99,7 @@ namespace TIAMWebApp.Client.Services
|
|||
//result = await response.Content.ReadAsStringAsync();
|
||||
return result;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async Task<(bool isSuccess, string ErrorMessage)> CreateUser(RegistrationModel regModel)
|
||||
|
|
@ -105,7 +109,7 @@ namespace TIAMWebApp.Client.Services
|
|||
string result = string.Empty;
|
||||
var url = APIUrls.CreateUser;
|
||||
|
||||
var response = await http.PostAsJsonAsync(url, regModel);
|
||||
var response = await http.PostAsJsonAsync(url, regModel);
|
||||
result = await response.Content.ReadAsStringAsync();
|
||||
/*if (response.IsSuccessStatusCode)
|
||||
{
|
||||
|
|
@ -122,25 +126,67 @@ namespace TIAMWebApp.Client.Services
|
|||
return (isSuccess, result);
|
||||
}
|
||||
|
||||
public async Task<bool> RefreshToken()
|
||||
{
|
||||
bool isTokenRefreshed = false;
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var url = APIUrls.RefreshToken;
|
||||
|
||||
var serializedStr = JsonConvert.SerializeObject(new AuthenticateRequestAndResponse
|
||||
{
|
||||
RefreshToken = Setting.UserBasicDetails.RefreshToken,
|
||||
AccessToken = Setting.UserBasicDetails.AccessToken
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
string contentStr = await response.Content.ReadAsStringAsync();
|
||||
var mainResponse = JsonConvert.DeserializeObject<MainResponse>(contentStr);
|
||||
if (mainResponse.IsSuccess)
|
||||
{
|
||||
var tokenDetails = JsonConvert.DeserializeObject<AuthenticateRequestAndResponse>(mainResponse.Content.ToString());
|
||||
Setting.UserBasicDetails.AccessToken = tokenDetails.AccessToken;
|
||||
Setting.UserBasicDetails.RefreshToken = tokenDetails.RefreshToken;
|
||||
|
||||
string userDetailsStr = JsonConvert.SerializeObject(Setting.UserBasicDetails);
|
||||
await secureStorageHandler.SaveToSecureStorageAsync(nameof(Setting.UserBasicDetails), userDetailsStr);
|
||||
isTokenRefreshed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = ex.Message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return isTokenRefreshed;
|
||||
}
|
||||
|
||||
|
||||
public Task<Dictionary<int, string>> GetUserRolesAsync(User user)
|
||||
{
|
||||
|
||||
//get the user's roles
|
||||
int role = User.UserRoles;
|
||||
int role = User.UserRoles;
|
||||
|
||||
foreach (var roleType in roleTypes)
|
||||
foreach (var roleType in roleTypes)
|
||||
{
|
||||
if ((role & roleType.Id) == roleType.Id)
|
||||
{
|
||||
if ((role & roleType.Id) == roleType.Id)
|
||||
{
|
||||
|
||||
//add the role to the dictionary
|
||||
userRoleTypes.Add(roleType.Id, roleType.RoleName);
|
||||
|
||||
}
|
||||
//add the role to the dictionary
|
||||
userRoleTypes.Add(roleType.Id, roleType.RoleName);
|
||||
|
||||
}
|
||||
}
|
||||
return Task.FromResult(userRoleTypes);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.10" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
export function get(key) {
|
||||
return window.sessionStorage.getItem(key);
|
||||
}
|
||||
|
||||
export function set(key, value) {
|
||||
window.sessionStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
export function clear() {
|
||||
window.sessionStorage.clear();
|
||||
}
|
||||
|
||||
export function remove(key) {
|
||||
window.sessionStorage.removeItem(key);
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
export function get(key) {
|
||||
return window.sessionStorage.getItem(key);
|
||||
}
|
||||
|
||||
export function set(key, value) {
|
||||
window.sessionStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
export function clear() {
|
||||
window.sessionStorage.clear();
|
||||
}
|
||||
|
||||
export function remove(key) {
|
||||
window.sessionStorage.removeItem(key);
|
||||
}
|
||||
|
|
@ -5,35 +5,48 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
using TIAMWebApp.Shared.Application.Models.PageModels;
|
||||
using TIAMWebApp.Server.Models;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using TIAMWebApp.Server.ModelsTIAMWebApp.Shared.Application.Models;
|
||||
|
||||
namespace TIAMWebApp.Server.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Route("api/[controller]")]
|
||||
public class UserAPIController : ControllerBase
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||
PasswordHasher hasher = new PasswordHasher();
|
||||
|
||||
|
||||
private User[] users = new User[]
|
||||
{
|
||||
new User("test@tiam.hu", "+36701234567", "asd123")
|
||||
new User(new Guid("540271f6-c604-4c16-8160-d5a7cafedf00"), "test@tiam.hu", "+36701234567", "Asdasd123456"),
|
||||
new User(new Guid("4cbaed43-2465-4d99-84f1-c8bc6b7025f7"), "adam@tiam.hu", "+36701234567", "Asdasd987654")
|
||||
|
||||
};
|
||||
|
||||
private readonly ILogger<SupplierAPIController> _logger;
|
||||
private readonly ILogger<UserAPIController> _logger;
|
||||
|
||||
public UserAPIController(ILogger<SupplierAPIController> logger)
|
||||
public UserAPIController(ILogger<UserAPIController> logger, IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_webHostEnvironment = webHostEnvironment;
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
/*[HttpPost]
|
||||
[Route("Auth")]
|
||||
public async Task<IActionResult> AuthenticateUser([FromBody] JsonElement SerializedLoginModel)
|
||||
{
|
||||
|
|
@ -50,7 +63,7 @@ namespace TIAMWebApp.Server.Controllers
|
|||
Console.WriteLine(user.Email);
|
||||
Console.WriteLine(user.Password);
|
||||
|
||||
if (user.Email == "test@tiam.hu" && user.Password == "asd123")
|
||||
if (user.Email == "test@tiam.hu" && user.Password == "Asdasd123456")
|
||||
{
|
||||
Console.WriteLine("User authenticated");
|
||||
return Ok("yes");
|
||||
|
|
@ -62,8 +75,178 @@ namespace TIAMWebApp.Server.Controllers
|
|||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("AuthenticateUser")]
|
||||
public async Task<IActionResult> AuthenticateUser([FromBody] JsonElement SerializedLoginModel)
|
||||
{
|
||||
|
||||
var authenticateUser = JObject.Parse(SerializedLoginModel.GetRawText()).ToObject<LoginModel>();
|
||||
|
||||
//check if user exists
|
||||
//var user = await _userManager.FindByNameAsync(authenticateUser.UserName);
|
||||
//if (user == null) return Unauthorized();
|
||||
|
||||
//mocking
|
||||
var user = users.FirstOrDefault(x => x.Email == authenticateUser.Email);
|
||||
|
||||
//check if password is valid
|
||||
//bool isValidUser = await _userManager.CheckPasswordAsync(user, authenticateUser.Password);
|
||||
|
||||
//mocking
|
||||
bool isValidUser = false;
|
||||
|
||||
if (user.Password == authenticateUser.Password)
|
||||
{
|
||||
isValidUser = true;
|
||||
|
||||
}
|
||||
|
||||
if (isValidUser)
|
||||
{
|
||||
Console.WriteLine("User authenticated, let's start JWT");
|
||||
string accessToken = GenerateAccessToken(user);
|
||||
Console.WriteLine("Generate refresh token");
|
||||
var refreshToken = GenerateRefreshToken();
|
||||
user.RefreshToken = refreshToken;
|
||||
//Update user with refreshToken!!
|
||||
//await _userManager.UpdateAsync(user);
|
||||
|
||||
var response = new MainResponse
|
||||
{
|
||||
Content = new AuthenticationResponse
|
||||
{
|
||||
RefreshToken = refreshToken,
|
||||
AccessToken = accessToken
|
||||
},
|
||||
IsSuccess = true,
|
||||
ErrorMessage = ""
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string GenerateAccessToken(User user)
|
||||
{
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var token = new JwtSecurityToken();
|
||||
Console.WriteLine("----------------------------------------------------------");
|
||||
var keyDetail = Encoding.UTF8.GetBytes(_configuration["JWT:Key"]);
|
||||
Console.WriteLine(_configuration["JWT:Key"]);
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||
new Claim(ClaimTypes.Email, user.Email)
|
||||
};
|
||||
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Audience = _configuration["JWT:Audience"],
|
||||
Issuer = _configuration["JWT:Issuer"],
|
||||
Expires = DateTime.UtcNow.AddMinutes(30),
|
||||
Subject = new ClaimsIdentity(claims),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyDetail), SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;
|
||||
string writtenToken = tokenHandler.WriteToken(token);
|
||||
Console.WriteLine(writtenToken);
|
||||
return writtenToken;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("RefreshToken")]
|
||||
public async Task<IActionResult> RefreshToken(RefreshTokenRequest refreshTokenRequest)
|
||||
{
|
||||
var response = new MainResponse();
|
||||
if (refreshTokenRequest is null)
|
||||
{
|
||||
response.ErrorMessage = "Invalid request";
|
||||
return BadRequest(response);
|
||||
}
|
||||
|
||||
var principal = GetPrincipalFromExpiredToken(refreshTokenRequest.AccessToken);
|
||||
|
||||
if (principal != null)
|
||||
{
|
||||
var email = principal.Claims.FirstOrDefault(f => f.Type == ClaimTypes.Email);
|
||||
|
||||
//var user = await _userManager.FindByEmailAsync(email?.Value);
|
||||
var user = users.FirstOrDefault(x => x.Email == email?.Value);
|
||||
|
||||
|
||||
if (user is null || user.RefreshToken != refreshTokenRequest.RefreshToken)
|
||||
{
|
||||
response.ErrorMessage = "Invalid Request";
|
||||
return BadRequest(response);
|
||||
}
|
||||
|
||||
string newAccessToken = GenerateAccessToken(user);
|
||||
string refreshToken = GenerateRefreshToken();
|
||||
|
||||
//mocking - update user with new refreshToken
|
||||
user.RefreshToken = refreshToken;
|
||||
//await _userManager.UpdateAsync(user);
|
||||
|
||||
response.IsSuccess = true;
|
||||
response.Content = new AuthenticationResponse
|
||||
{
|
||||
RefreshToken = refreshToken,
|
||||
AccessToken = newAccessToken
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound("Invalid Token Found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
||||
{
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
var keyDetail = Encoding.UTF8.GetBytes(_configuration["JWT:Key"]);
|
||||
|
||||
var tokenValidationParameter = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = false,
|
||||
ValidateAudience = false,
|
||||
ValidateLifetime = false,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = _configuration["JWT:Issuer"],
|
||||
ValidAudience = _configuration["JWT:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(keyDetail),
|
||||
};
|
||||
|
||||
SecurityToken securityToken;
|
||||
var principal = tokenHandler.ValidateToken(token, tokenValidationParameter, out securityToken);
|
||||
var jwtSecurityToken = securityToken as JwtSecurityToken;
|
||||
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new SecurityTokenException("Invalid token");
|
||||
return principal;
|
||||
}
|
||||
|
||||
private string GenerateRefreshToken()
|
||||
{
|
||||
|
||||
var randomNumber = new byte[32];
|
||||
using (var rng = RandomNumberGenerator.Create())
|
||||
{
|
||||
rng.GetBytes(randomNumber);
|
||||
return Convert.ToBase64String(randomNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("CreateUser")]
|
||||
public async Task<IActionResult> CreateUser([FromBody] JsonElement SerializedRegistrationModel)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
namespace TIAMWebApp.Server.Models
|
||||
{
|
||||
|
||||
public class AuthenticateUser
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace TIAMWebApp.Server.Models
|
||||
{
|
||||
public class RefreshTokenRequest
|
||||
{
|
||||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -4,11 +4,13 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using TIAM.Database.DataLayers;
|
||||
using TIAM.Entities.TransferDestinations;
|
||||
using TIAM.Database.DbContexts;
|
||||
using TIAM.Database.DataLayers.TransferDestinations;
|
||||
using TIAM.Database.DataLayers.Users;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
|
@ -16,9 +18,72 @@ var builder = WebApplication.CreateBuilder(args);
|
|||
|
||||
builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddRazorPages();
|
||||
//builder.Services.AddDbContext<TransferDestinationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DeveloperDbConnection")));
|
||||
//builder.Services.AddScoped<TiamDalBase<TransferDestinationDbContext>>(x => x.GetService<TransferDestinationDbContext>());
|
||||
builder.Services.AddScoped<UserDal>();
|
||||
builder.Services.AddDbContext<TransferDestinationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DeveloperDbConnection")));;
|
||||
|
||||
builder.Services.AddSwaggerGen(swagger =>
|
||||
{
|
||||
swagger.SwaggerDoc("v1",
|
||||
new OpenApiInfo
|
||||
{
|
||||
Title = "API Title",
|
||||
Version = "V1",
|
||||
Description = "API Description"
|
||||
});
|
||||
|
||||
var securitySchema = new OpenApiSecurityScheme
|
||||
{
|
||||
Description = "Authorization header using the Bearer scheme. Example \"Authorization: Bearer {token}\"",
|
||||
Name = "Authorization",
|
||||
In = ParameterLocation.Header,
|
||||
Type = SecuritySchemeType.Http,
|
||||
Scheme = "Bearer",
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
};
|
||||
swagger.AddSecurityDefinition(securitySchema.Reference.Id, securitySchema);
|
||||
swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{securitySchema,Array.Empty<string>() }
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddAuthentication(f =>
|
||||
{
|
||||
f.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
f.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
}).AddJwtBearer(k =>
|
||||
{
|
||||
var Key = Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]);
|
||||
k.SaveToken = true;
|
||||
k.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = builder.Configuration["JWT:Issuer"],
|
||||
ValidAudience = builder.Configuration["JWT:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Key),
|
||||
ClockSkew = TimeSpan.Zero
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.ConfigureApplicationCookie(options =>
|
||||
{
|
||||
options.Cookie.HttpOnly = false;
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = "/Login";
|
||||
options.SlidingExpiration = true;
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
|
@ -34,12 +99,21 @@ else
|
|||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
|
||||
});
|
||||
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
app.UseBlazorFrameworkFiles();
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseRouting();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
app.MapRazorPages();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GoogleApi" Version="5.2.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.13" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.11" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -4,5 +4,10 @@
|
|||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JWT": {
|
||||
"Key": "Cee4400-rDMFkVvHPufyLDSzbfu2grgRhpepos299IhTLOXsljkcpt3yUR4RRjPQ",
|
||||
"Issuer": "https://localhost:7116",
|
||||
"Audience": "http://localhost:7116"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,10 @@
|
|||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
"AllowedHosts": "*",
|
||||
"JWT": {
|
||||
"Key": "Cee4400-rDMFkVvHPufyLDSzbfu2grgRhpepos299IhTLOXsljkcpt3yUR4RRjPQ",
|
||||
"Issuer": "http://localhost:5000",
|
||||
"Audience": "http://localhost:5000"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Interfaces
|
||||
{
|
||||
public interface ISecureStorageHandler
|
||||
{
|
||||
public Task SaveToSecureStorageAsync(string key, string value);
|
||||
public Task<string> GetFromSecureStorageAsync(string key);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,5 +23,7 @@ namespace TIAMWebApp.Shared.Application.Interfaces
|
|||
public Task<string> TestUserApi(int Param);
|
||||
|
||||
public Task<Dictionary<int, string>> GetUserRolesAsync(User user);
|
||||
|
||||
Task<bool> RefreshToken();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,9 +8,10 @@ namespace TIAMWebApp.Shared.Application.Models
|
|||
{
|
||||
public class APIUrls
|
||||
{
|
||||
public const string UserTest = "UserAPI/test1";
|
||||
public const string AuthenticateUser = "UserAPI/Auth";
|
||||
public const string CreateUser = "UserAPI/CreateUser";
|
||||
public const string UserTest = "api/UserAPI/test1";
|
||||
public const string AuthenticateUser = "api/UserAPI/AuthenticateUser";
|
||||
public const string CreateUser = "api/UserAPI/CreateUser";
|
||||
public const string RefreshToken = "api/UserAPI/RefreshToken";
|
||||
public const string WeatherForecast = "WeatherForecastAPI";
|
||||
public const string PopulationStructure = "PopulationStructureAPI";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class AuthenticateRequestAndResponse
|
||||
{
|
||||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class AuthenticationResponse
|
||||
{
|
||||
public string? AccessToken { get; set; }
|
||||
public string? RefreshToken { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models.ClientSide
|
||||
{
|
||||
public class Setting
|
||||
{
|
||||
public static UserBasicDetails UserBasicDetails { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models.ClientSide
|
||||
{
|
||||
public class UserBasicDetails
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
|
||||
public UserBasicDetails(string userId, string email, string token, string refreshToken)
|
||||
{
|
||||
UserId = userId;
|
||||
Email = email;
|
||||
AccessToken = token;
|
||||
RefreshToken = refreshToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
namespace TIAMWebApp.Server.ModelsTIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class ErrorResponse
|
||||
{
|
||||
public static MainResponse ReturnErrorResponse(string errorMessage)
|
||||
{
|
||||
return new MainResponse
|
||||
{
|
||||
ErrorMessage = errorMessage,
|
||||
IsSuccess = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class MainResponse
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
public object? Content { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
namespace TIAMWebApp.Shared.Application.Models
|
||||
{
|
||||
public class User
|
||||
public class User
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Email { get; set; }
|
||||
|
|
@ -15,6 +9,7 @@ namespace TIAMWebApp.Shared.Application.Models
|
|||
public bool IsLoggedIn { get; set; }
|
||||
public UserType UserType { get; set; }
|
||||
public int UserRoles { get; set; }
|
||||
public string? RefreshToken { get; set; }
|
||||
public Dictionary<int, string> UserRolesDictionary { get; set; }
|
||||
|
||||
public User(string email, string phonenumber, string password)
|
||||
|
|
@ -26,6 +21,15 @@ namespace TIAMWebApp.Shared.Application.Models
|
|||
UserRolesDictionary = new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
public User(Guid id, string email, string phonenumber, string password)
|
||||
{
|
||||
Id = id;
|
||||
Email = email;
|
||||
Password = password;
|
||||
PhoneNumber = phonenumber;
|
||||
UserRolesDictionary = new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum UserType
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.39" />
|
||||
<PackageReference Include="Microsoft.JSInterop" Version="7.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,10 @@
|
|||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TIAMWebApp.Shared.Application.Models;
|
||||
|
||||
namespace TIAMWebApp.Shared.Application.Utility
|
||||
{
|
||||
internal class LogToBrowserConsole
|
||||
public class LogToBrowserConsole
|
||||
{
|
||||
private readonly JSRuntime jsRuntime;
|
||||
|
||||
public LogToBrowserConsole(JSRuntime jSRuntime)
|
||||
{
|
||||
this.jsRuntime = jsRuntime;
|
||||
}
|
||||
private readonly JSRuntime jsRuntime;
|
||||
|
||||
public void LogToBC(string message)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue