This commit is contained in:
jozsef.b@aycode.com 2024-05-22 11:24:00 +02:00
commit 24d6ea5b68
21 changed files with 676 additions and 20 deletions

View File

@ -1,6 +1,7 @@
@using TIAMSharedUI.Shared
@using Microsoft.AspNetCore.Components.Authorization
@using TIAMSharedUI.Shared
<Router AppAssembly="@typeof(Main).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
@* <Router AppAssembly="@typeof(Main).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
@ -10,4 +11,23 @@
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</Router> *@
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Main).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<p>Sorry dude, but you're not authorized!</p>
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

View File

@ -9,6 +9,7 @@ using TIAMWebApp.Shared.Application.Services;
using BlazorAnimation;
using AyCode.Core.Loggers;
using AyCode.Services.Loggers;
using Microsoft.AspNetCore.Components.Authorization;
namespace TIAMMobileApp
{
@ -64,6 +65,8 @@ namespace TIAMMobileApp
builder.Services.AddSingleton(x => new ResourceManager("TIAMWebApp.Shared.Application.Resources", typeof(Main).Assembly));
builder.Services.AddSingleton<SignalRService>();
builder.Services.AddSingleton<SumupService>();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
builder.Services.AddAuthorizationCore();
builder.Services.Configure<AnimationOptions>(Guid.NewGuid().ToString(), c => { });
return builder.Build();
}

View File

@ -1,4 +1,5 @@
@* @page "/"; *@
@using Microsoft.AspNetCore.Components.Authorization
@using TIAMWebApp.Shared.Application.Interfaces
@using TIAMWebApp.Shared.Application.Models
@using TIAMWebApp.Shared.Application.Utility
@ -19,6 +20,7 @@
@inject ISessionService sessionService;
@inject HttpClient http;
@inject IComponentUpdateService ComponentUpdateService
@inject AuthenticationStateProvider AuthStateProvider
@{
if (string.IsNullOrWhiteSpace(TrackingId))
@ -83,7 +85,9 @@
if (isTokenRefreshed)
{
await AuthStateProvider.GetAuthenticationStateAsync();
_logger.Info("Token refreshed");
}
else
{
@ -97,7 +101,7 @@
else
{
_logger.Info("Valid token found");
await AuthStateProvider.GetAuthenticationStateAsync();
}
string _userId = jsontoken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.NameId).Value;

View File

@ -30,14 +30,23 @@
</div>
</div>
<NavLink href="tictactoe">
TicTacToe
</NavLink>
<NavLink href="create-payment">
Create Payment
</NavLink>
<NavLink href="@($"mytransfers/{Guid.Parse("108E5A63-AA9E-47BE-ACFA-00306FFC5215")}")">
My trasnfers
</NavLink>
@code {
private string userName;
private string newMessage;
private List<string> messages = new List<string>();
//private string hrefString = "mytransfers/" + "108E5A63-AA9E-47BE-ACFA-00306FFC5215";
protected override async Task OnInitializedAsync()
{

View File

@ -0,0 +1,283 @@
@page "/mytransfers/{transferId:guid}"
@using TIAM.Entities.Transfers
@using TIAMWebApp.Shared.Application.Interfaces
@using AyCode.Core.Loggers
@using AyCode.Services.Loggers
@using TIAM.Core.Loggers
@using TIAM.Core.Enums
@using TIAMWebApp.Shared.Application.Utility
@inject HttpClient Http
@inject NavigationManager navManager
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject ITransferDataService transferDataService
<PageTitle>Transfer details</PageTitle>
<div class="text-center m-5">
<h1>Transfer details</h1>
<h2 style="font-size:small">Manage your transfer here</h2>
</div>
@if (isLoading)
{
<div class="text-center m-5">
<DxWaitIndicator Visible="true"
CssClass="m-auto"
AnimationType="WaitIndicatorAnimationType.Spin" />
</div>
}
else if (!string.IsNullOrEmpty(errorMessage))
{
<div class="alert alert-danger">@errorMessage</div>
}
else
{
<div class="container mt-4">
@if (!editMode)
{
<section>
<div class="container py-4">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-md-10 col-lg-8 col-xl-6">
<div class="card" style="border-radius: 16px;">
<div class="card-header py-3 px-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<span class="fw-bold text-body">Transfer identifier: @transfer.Id</span>
<p class="text-muted mb-0">@transfer.ContactPhone</p>
</div>
</div>
</div>
<div class="card-body p-4">
<div class="mb-4 pb-2">
<div class="mb-3">
<h4 class="fw-bold">Passenger: @transfer.FullName</h4>
<h4 class="fw-bold">E-mail address: @transfer.ContactEmail</h4>
<h5 class="text-muted">From: @transfer.FromAddress</h5>
<h5 class="text-muted">To: @transfer.ToAddress</h5>
<h5>@transfer.Appointment.ToString("MMMM dd, yyyy")</h5>
<h5 class="mb-3 text-muted">@transfer.Appointment.ToString("hh:mm tt")</h5>
<p>Passengers: @transfer.PassengerCount</p>
<p>Luggage: @transfer.LuggageCount</p>
<p>Flight number (optional): @transfer.FlightNumber</p>
<hr />
<h3>License plate: POX-382</h3>
<p class="text-muted">Car looks: Silver, Toyota, Prius</p>
<hr />
<p class="text-muted">Status on: <span class="text-body">@DateTime.Now.ToString("hh:mm tt"), @DateTime.Today.ToString("MMMM dd, yyyy")</span></p>
</div>
</div>
<div class="d-flex justify-content-between align-items-center">
<h4>EUR @transfer.Price <span class="small text-muted"> </span></h4>
</div>
</div>
<div class="card-footer p-4">
<div class="d-flex justify-content-between align-items-center">
<h5 class="fw-normal mb-0"><a href="#!" class="text-decoration-none">Contact driver</a></h5>
<div class="vr"></div>
<h5 class="fw-normal mb-0"><a href="#!" class="text-decoration-none">Cancel</a></h5>
<div class="vr"></div>
<h5 class="fw-normal mb-0"><a class="btn btn-primary">Pay</a></h5>
<div class="vr"></div>
<h5 class="fw-normal mb-0"><a class="btn btn-secondary" @onclick="SetEditMode">Modify</a></h5>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
}
else
{
<section>
<div class="container py-1">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-md-10 col-lg-8 col-xl-6">
<DxFormLayout>
<div class="card card-admin card-stepper" style="border-radius: 16px;">
<div class="card-header py-2 px-4">
<div class="d-flex justify-content-between align-items-center">
<div>
<span class="fw-bold text-body">Transfer identifier: @transfer.Id</span>
<p class="text-muted">
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field dxbl-col-12" Caption="Contact Phone">
<DxTextBox @bind-Text="transfer.ContactPhone" />
</DxFormLayoutItem>
</p>
</div>
<div>
<h6 class="mb-0"> </h6>
</div>
</div>
</div>
<div class="card-body p-4">
<div class="d-flex flex-row mb-4 pb-2">
<div class="flex-fill">
<DxFormLayoutItem ColSpanLg="6" CssClass="form-field" Caption="First Name">
<DxTextBox @bind-Text="transfer.FirstName" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="6" CssClass="form-field" Caption="Last Name">
<DxTextBox @bind-Text="transfer.LastName" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Contact Email">
<DxTextBox @bind-Text="transfer.ContactEmail" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="From Address">
<DxTextBox @bind-Text="transfer.FromAddress" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="To Address">
<DxTextBox @bind-Text="transfer.ToAddress" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Appointment">
<DxDateEdit TimeSectionVisible="true" @bind-Date="transfer.Appointment" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Passenger Count">
<DxSpinEdit @bind-Value="transfer.PassengerCount" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Luggage Count">
<DxSpinEdit @bind-Value="transfer.LuggageCount" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Flight Number">
<DxTextBox @bind-Text="transfer.FlightNumber" />
</DxFormLayoutItem>
<hr />
<h4>License plate: POX-382</h4>
<p class="text-muted">Car looks: Silver, Toyota, Prius</p>
<hr />
<p class="text-muted">Status on: <span class="text-body">@DateTime.Now.TimeOfDay, @DateTime.Today.Date</span></p>
</div>
</div>
<!--ul id="progressbar-1" class="mx-0 mt-0 mb-5 px-0 pt-0 pb-4">
<li class="step0 active" id="step1">
<span style="margin-left: 22px; margin-top: 12px;">PLACED</span>
</li>
<li class="step0 active text-center" id="step2"><span>WAITING FOR PICK UP</span></li>
<li class="step0 text-muted text-end" id="step3">
<span style="margin-right: 22px;">ARRIVED</span>
</li>
</ul-->
<div class="d-flex flex-row mb-4 pb-2">
<h4> EUR @transfer.Price <span class="small text-muted"> via (COD) </span></h4>
</div>
<div class="d-flex flex-row mb-4 pb-2">
<DxFormLayoutItem ColSpanLg="12" CssClass="form-field" Caption="Comment">
<DxMemo @bind-Text="transfer.Comment" />
</DxFormLayoutItem>
</div>
</div>
<div class="card-footer p-4">
<div class="d-flex justify-content-between">
<DxButton Click="UpdateTransfer">Save Changes</DxButton>
</div>
</div>
</div>
</DxFormLayout>
</div>
</div>
</div>
</section>
}
</div>
}
@code {
[Parameter]
public Guid transferId { get; set; } = Guid.Empty;
private Transfer transfer = new Transfer();
private bool isLoading = true;
private string errorMessage = string.Empty;
private LoggerClient<EditTransfers> _logger;
List<string> StatusTypes = new List<string>();
private bool editMode = false;
protected override async Task OnInitializedAsync()
{
foreach (var t in Enum.GetValues(typeof(TransferStatusType)).OfType<TransferStatusType>().ToList())
StatusTypes.Add(t.ToString());
_logger = new LoggerClient<EditTransfers>(LogWriters.ToArray());
_logger.Info($"parameter: {transferId.ToString()}");
await LoadTransfer();
}
protected override async Task OnParametersSetAsync()
{
_logger.Info($"on parameter set: {transferId.ToString()}");
base.OnParametersSet();
}
private void SetEditMode()
{
editMode = true;
}
private async Task LoadTransfer()
{
try
{
var response = await transferDataService.GetTransferByIdAsync(transferId);
if (response != null)
{
transfer = response;
}
else
{
errorMessage = $"Error loading transfer: {transfer.Id}";
}
}
catch (Exception ex)
{
errorMessage = $"Exception: {ex.Message}";
}
isLoading = false;
}
private async Task UpdateTransfer()
{
try
{
var result = await transferDataService.UpdateTransferAsync(transfer);
if (result)
{
navManager.NavigateTo("/mytransfers"); // Redirect to a list or another page after successful update
}
else
{
errorMessage = $"Error updating transfer: {result.ToString()}";
}
}
catch (Exception ex)
{
errorMessage = $"Exception: {ex.Message}";
}
}
}

View File

@ -15,6 +15,7 @@ using AyCode.Blazor.Components;
using AyCode.Core.Loggers;
using AyCode.Services.Loggers;
using Azure.Core;
using Microsoft.AspNetCore.Components.Authorization;
namespace TIAMSharedUI.Pages
{
@ -35,9 +36,12 @@ namespace TIAMSharedUI.Pages
public IStringLocalizer<MyResources> localizer { get; set; }
[Inject]
public ISessionService sessionService { get; set; }
[Inject]
public AuthenticationStateProvider AuthStateProvider { get; set; }
//fill loginmodel with fake but valid data
//LoginModel loginModel = new();
//[Display(Name = "LoginTitleText", ResourceType = typeof(MyResources))]
@ -101,8 +105,8 @@ namespace TIAMSharedUI.Pages
//save to local storage
await secureStorageHandler.SaveToSecureStorageAsync(nameof(Setting.UserBasicDetails), userBasicDetailsJson);
await AuthStateProvider.GetAuthenticationStateAsync();
if (!mainResponse.IsSuccess)
{

View File

@ -0,0 +1,117 @@
@page "/tictactoe"
@using Microsoft.AspNetCore.SignalR.Client
@using AyCode.Core.Loggers
@using AyCode.Services.Loggers
@using TIAM.Core.Loggers
@using TIAMWebApp.Shared.Application.Utility
@inject NavigationManager Navigation
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
<h3>Tic Tac Toe</h3>
<div class="game-board">
@for (int i = 0; i < 3; i++)
{
<div class="board-row">
@for (int j = 0; j < 3; j++)
{
<button class="square" @onclick="() => MakeMove(i, j)">
@board[i, j]
</button>
}
</div>
}
</div>
<div class="status">
@if (!string.IsNullOrEmpty(winner))
{
<p>@winner wins!</p>
}
else if (board.Cast<string>().All(cell => cell != null))
{
<p>It's a draw!</p>
}
else
{
<p>Next player: @currentPlayer</p>
}
</div>
@code {
private string[,] board = new string[3, 3];
private string currentPlayer = "X";
private string winner;
private HubConnection hubConnection;
private string groupName = "tictactoe";
private LoggerClient<TicTacToe> _logger;
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<TicTacToe>(LogWriters.ToArray());
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/gamehub"))
.Build();
hubConnection.On<int, int, string>("ReceiveMove", (row, col, player) =>
{
if (row >= 0 && row < 3 && col >= 0 && col < 3)
{
board[row, col] = player;
if (CheckWinner())
{
winner = player;
}
StateHasChanged();
}
});
await hubConnection.StartAsync();
await JoinGameGroup();
}
private async Task JoinGameGroup()
{
await hubConnection.SendAsync("JoinGame", groupName);
}
private async Task MakeMove(int row, int col)
{
_logger.DetailConditional($"row: {row}, col: {col}");
if (row >= 0 && row < 3 && col >= 0 && col < 3 && board[row, col] == null && winner == null)
{
board[row, col] = currentPlayer;
if (CheckWinner())
{
winner = currentPlayer;
}
await hubConnection.SendAsync("MakeMove", groupName, row, col, currentPlayer);
currentPlayer = currentPlayer == "X" ? "O" : "X";
}
}
private bool CheckWinner()
{
// Check rows, columns and diagonals for a win
for (int i = 0; i < 3; i++)
{
if (board[i, 0] != null && board[i, 0] == board[i, 1] && board[i, 1] == board[i, 2])
{
return true;
}
if (board[0, i] != null && board[0, i] == board[1, i] && board[1, i] == board[2, i])
{
return true;
}
}
if (board[0, 0] != null && board[0, 0] == board[1, 1] && board[1, 1] == board[2, 2])
{
return true;
}
if (board[0, 2] != null && board[0, 2] == board[1, 1] && board[1, 1] == board[2, 0])
{
return true;
}
return false;
}
}

View File

@ -0,0 +1,25 @@
.game-board {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 10px;
margin-bottom: 20px;
}
.board-row {
display: contents;
}
.square {
width: 100px;
height: 100px;
font-size: 2rem;
text-align: center;
vertical-align: middle;
line-height: 100px;
border: 1px solid #000;
}
.status {
margin-top: 20px;
font-size: 1.2rem;
}

View File

@ -1,4 +1,4 @@
@page "/mytransfer"
@page "/mytransfers"
<PageTitle>Transferdetails</PageTitle>

View File

@ -1,5 +1,6 @@
@inherits LayoutComponentBase
@using Microsoft.AspNetCore.Authorization
@using TIAMSharedUI.Shared.Users
@using AyCode.Core.Extensions
@using AyCode.Interfaces.StorageHandlers;
@ -23,6 +24,7 @@
@inject ISessionService sessionService
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject IUserDataService userDataService
@attribute [Authorize]
<div class="page">

View File

@ -395,9 +395,9 @@ select:focus-visible {
border: none;
outline: none;
background: none;
font-size: 1.2rem;
/*font-size: 1.2rem;*/
color: #666;
padding: 10px 15px 10px 10px;
/*padding: 10px 15px 10px 10px;*/
/* border: 1px solid red; */
}

View File

@ -1,5 +1,6 @@
@using TIAMSharedUI.Shared
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
@using Microsoft.AspNetCore.Components.Authorization
@using TIAMSharedUI.Shared
@* <Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
@ -10,4 +11,22 @@
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</Router> *@
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new [] { typeof(MainLayout).Assembly}">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<p>Sorry dude, but you're not authorized!</p>
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

View File

@ -4,7 +4,7 @@ using Blazored.LocalStorage;
using DevExpress.Blazor;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.JSInterop;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Reflection;
using System.Resources;
using AyCode.Core.Loggers;
@ -15,6 +15,8 @@ using TIAMWebApp.Shared.Application.Services;
using TIAMWebApp.Shared.Application.Utility;
using AyCode.Services.Loggers;
using System.Net;
using Microsoft.AspNetCore.Components.Authorization;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
@ -45,7 +47,8 @@ builder.Services.AddSingleton<IAcLogWriterClientBase, SignaRClientLogItemWriter>
//builder.Services.AddSingleton<DevAdminSignalClient>();
builder.Services.AddSingleton<SignalRService>();
builder.Services.AddSingleton<SumupService>();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
builder.Services.AddAuthorizationCore();
//builder.Services.AddScoped<BrowserConsoleLogWriter>();
//WebSpecific end

View File

@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.5" PrivateAssets="all" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.8" />

View File

@ -15,6 +15,7 @@ using TIAM.Services.Server;
using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Models.ClientSide.Messages;
using TIAMWebApp.Shared.Application.Services;
using TIAMWebApp.Server.Services;
namespace TIAMWebApp.Server.Controllers
{
@ -39,14 +40,16 @@ namespace TIAMWebApp.Server.Controllers
private readonly TIAM.Core.Loggers.ILogger _logger;
private readonly TransferBackendService _transferBackendService;
private readonly IMessageSenderService _messageSenderService;
private readonly AuthService _authService;
public TransferDataAPIController(AdminDal adminDal, TransferBackendService transferBackendService, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters)
public TransferDataAPIController(AdminDal adminDal, TransferBackendService transferBackendService, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters, AuthService authService)
{
_adminDal = adminDal;
_transferBackendService = transferBackendService;
_logger = new TIAM.Core.Loggers.Logger<TransferDataAPIController>(logWriters.ToArray());
_messageSenderService = messageSenderService;
_authService = authService;
}
@ -371,16 +374,30 @@ namespace TIAMWebApp.Server.Controllers
}
}
[AllowAnonymous]
[Authorize]
[HttpGet]
[Route(APIUrls.GetTransfersRouteName)]
public async Task<string> GetTransfers()
{
var token = _authService.GetAuthTokenFromRequest(Request);
_logger.Detail(token);
var result = await _adminDal.GetTransfersJsonAsync();
return result;
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.GetTransferByIdRouteName)]
public async Task<IActionResult> GetTransferById([FromBody] Guid transferID)
{
_logger.Info(@"Get transfer by id called");
_logger.Info($"transferId: {transferID.ToString()}");
var result = _adminDal.GetTransferById(transferID);
//TODO: Implementálni a Logout-ot kliens és szerver oldalon is! - J.
return Ok(result);
}
[AllowAnonymous]
[HttpPost]

View File

@ -41,6 +41,7 @@ builder.Services.AddScoped<UserDal>();
builder.Services.AddScoped<AdminDal>();
builder.Services.AddScoped<AuctionDal>();
builder.Services.AddScoped<TransferDestinationDal>();
builder.Services.AddSingleton<AuthService>();
builder.Services.AddSignalR().AddMessagePackProtocol(options => options.SerializerOptions = MessagePackSerializerOptions.Standard.WithSecurity(MessagePackSecurity.UntrustedData));
@ -179,6 +180,7 @@ app.MapBlazorHub();
app.MapHub<SignalRHub>("/TiamChatHub");
app.MapHub<LoggerSignalRHub>("/TiamLoggerHub");
//app.MapHub<DevAdminSignalRHub>("/DevAdminHub");
app.MapHub<GameHub>("/gamehub");
app.MapFallbackToFile("index.html");

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
namespace TIAMWebApp.Server.Services
{
public class AuthService
{
public string GetAuthTokenFromRequest(HttpRequest request)
{
// Check if the Authorization header is present
if (request.Headers.ContainsKey("Authorization"))
{
// Extract the token from the Authorization header
var authHeader = request.Headers["Authorization"].ToString();
if (authHeader.StartsWith("Bearer ", System.StringComparison.OrdinalIgnoreCase))
{
return authHeader.Substring("Bearer ".Length).Trim();
}
}
return null;
}
}
}

View File

@ -0,0 +1,37 @@
using AyCode.Core.Loggers;
using Microsoft.AspNetCore.SignalR;
using System.Net.Http;
using TIAM.Core.Loggers;
namespace TIAMWebApp.Server.Services;
public class GameHub : Hub
{
private readonly TIAM.Core.Loggers.ILogger _logger;
public GameHub(IEnumerable<IAcLogWriterBase> logWriters)
{
_logger = new TIAM.Core.Loggers.Logger<SumupService>(logWriters.ToArray());
}
public async Task MakeMove(string groupName, int row, int col, string player)
{
_logger.Detail($"{groupName}, {row}, {col}, {player}");
await Clients.Group(groupName).SendAsync("ReceiveMove", row, col, player);
}
public async Task JoinGame(string groupName)
{
_logger.Detail(groupName);
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("PlayerJoined", Context.ConnectionId);
}
public async Task LeaveGame(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("PlayerLeft", Context.ConnectionId);
}
}

View File

@ -0,0 +1,78 @@
using AyCode.Interfaces.StorageHandlers;
using Microsoft.AspNetCore.Components.Authorization;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Json;
using TIAMWebApp.Shared.Application.Models.ClientSide;
namespace TIAMWebApp.Shared.Application.Services
{
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private readonly ISecureStorageHandler _localStorage;
private readonly HttpClient _http;
public CustomAuthStateProvider(ISecureStorageHandler localStorage, HttpClient http)
{
_localStorage = localStorage;
_http = http;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
string userDetailsStr = await _localStorage.GetFromSecureStorageAsync(nameof(Setting.UserBasicDetails));
AuthenticationState state = null;
if (!string.IsNullOrEmpty(userDetailsStr))
{
var userBasicDetail = JsonConvert.DeserializeObject<UserBasicDetails>(userDetailsStr);
//var handler = new JwtSecurityTokenHandler();
//var jsontoken = handler.ReadToken(userBasicDetail?.AccessToken) as JwtSecurityToken;
var token = userBasicDetail?.AccessToken;
var identity = new ClaimsIdentity();
_http.DefaultRequestHeaders.Authorization = null;
if (!string.IsNullOrEmpty(token))
{
identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token.Replace("\"", ""));
}
var user = new ClaimsPrincipal(identity);
state = new AuthenticationState(user);
NotifyAuthenticationStateChanged(Task.FromResult(state));
}
else
{
state = new AuthenticationState(new ClaimsPrincipal());
}
return state;
}
public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
var payload = jwt.Split('.')[1];
var jsonBytes = ParseBase64WithoutPadding(payload);
var keyValuePairs = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()));
}
private static byte[] ParseBase64WithoutPadding(string base64)
{
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
return Convert.FromBase64String(base64);
}
}
}

View File

@ -152,13 +152,18 @@ namespace TIAMWebApp.Shared.Application.Services
public async Task<Transfer?> GetTransferByIdAsync(Guid id)
{
Transfer resultTransfer;
var url = $"{Setting.ApiBaseUrl}/{APIUrls.GetTransferById}";
//var url = $"{APIUrls.GetTransferDestinations}";
_logger.Info(url);
Transfer? response = await _http.GetFromJsonAsync<Transfer>(url);
var response = await _http.PostAsJsonAsync(url, id);
if (response == null)
return new Transfer();
return response;
else
{
resultTransfer = (Transfer)(await response.Content.ReadFromJsonAsync(typeof(Transfer)));
}
return resultTransfer;
}
public async Task<List<Transfer>> GetTransfersAsync()

View File

@ -22,6 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.5" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.5" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="8.0.5" />