first commit
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
using Fitness_core_BE.Auth;
|
||||
using Fitness_core_BE.Helpers;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Fitness_core_BE.Hubs
|
||||
{
|
||||
/// <summary>
|
||||
/// Tenant-isolated browser channel for device inventory, attendance, and access
|
||||
/// state notifications. The client id is always resolved from the authenticated
|
||||
/// user and is never accepted from the browser.
|
||||
/// </summary>
|
||||
[Authorize(AuthenticationSchemes = UserJwtDefaults.AuthenticationScheme)]
|
||||
public sealed class AccessHub : Hub
|
||||
{
|
||||
private readonly UserRoleHelper _userRoleHelper;
|
||||
|
||||
public AccessHub(UserRoleHelper userRoleHelper)
|
||||
{
|
||||
_userRoleHelper = userRoleHelper;
|
||||
}
|
||||
|
||||
public static string ClientGroup(Guid clientId) => $"access-client-{clientId:N}";
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
var userIdValue = Context.User?.FindFirst("UserId")?.Value;
|
||||
if (!Guid.TryParse(userIdValue, out var userId))
|
||||
throw new HubException("Authenticated user id is missing.");
|
||||
|
||||
var clientId = await _userRoleHelper.GetClientId(userId);
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, ClientGroup(clientId));
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
using Fitness_core_BE.AI;
|
||||
using Fitness_core_BE.Helpers;
|
||||
using Fitness_core_BE.Interfaces.Services;
|
||||
using Fitness_core_BE.Models;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Numerics;
|
||||
using System.Text.Json;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Fitness_core_BE.Hubs
|
||||
{
|
||||
public class ChatHub : Hub
|
||||
{
|
||||
private readonly IChatService _chatService;
|
||||
public readonly MealPlanOrchestrator _mealPlanOrchestrator;
|
||||
public readonly WorkoutPlanOrchestrator _workoutPlanOrchestrator;
|
||||
|
||||
public ChatHub(IChatService chatService, MealPlanOrchestrator mealPlanOrchestrator, WorkoutPlanOrchestrator workoutPlanOrchestrator)
|
||||
{
|
||||
_chatService = chatService;
|
||||
_mealPlanOrchestrator = mealPlanOrchestrator;
|
||||
_workoutPlanOrchestrator = workoutPlanOrchestrator;
|
||||
}
|
||||
|
||||
private Guid ResolveUserId()
|
||||
{
|
||||
// Later: Context.User.Claims (JWT)
|
||||
return Guid.Parse("d12fb5a6-969c-4fb2-a7f8-a5bc54ed0f11");
|
||||
}
|
||||
|
||||
public async Task JoinChat(object payload)
|
||||
{
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
Guid chatId = DataExtractor.GetRequiredGuid(data, "chatId");
|
||||
|
||||
//Guid userId = ResolveUserId();
|
||||
Guid userId = DataExtractor.GetRequiredGuid(data, "userId");
|
||||
|
||||
if (!await _chatService.CanUserAccessChatAsync(chatId, userId))
|
||||
throw new HubException("Unauthorized to join this chat");
|
||||
|
||||
await Groups.AddToGroupAsync(
|
||||
Context.ConnectionId,
|
||||
$"chat-{chatId}"
|
||||
);
|
||||
|
||||
var history = await _chatService.GetMessagesAsync(new
|
||||
{
|
||||
chatId = chatId,
|
||||
userId = userId,
|
||||
skip = 0,
|
||||
take = 30
|
||||
});
|
||||
|
||||
await Clients.Caller.SendAsync("ReceiveHistory", history);
|
||||
}
|
||||
|
||||
public async Task SendMessage(object payload)
|
||||
{
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
string reason = DataExtractor.GetRequiredString(data, "reason");
|
||||
Guid chatId = DataExtractor.GetRequiredGuid(data, "chatId");
|
||||
Guid userId = DataExtractor.GetRequiredGuid(data, "userId");
|
||||
string message = DataExtractor.GetRequiredString(data, "message");
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case "user":
|
||||
var savedMessage = await _chatService.SendMessageAsync(new
|
||||
{
|
||||
chatId = chatId,
|
||||
senderId = userId,
|
||||
message = message,
|
||||
type = "userMessages"
|
||||
});
|
||||
|
||||
await Clients.Group($"chat-{chatId}")
|
||||
.SendAsync("ReceiveMessage", savedMessage);
|
||||
break;
|
||||
|
||||
case "mealPlan":
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
userId,
|
||||
message,
|
||||
"userMealReq"
|
||||
);
|
||||
string messageType = DataExtractor.GetRequiredString(data, "messageType");
|
||||
if (messageType == "generateMealPlan")
|
||||
{
|
||||
var plan = await _mealPlanOrchestrator
|
||||
.GeneratePlanAsync(payload);
|
||||
|
||||
string aiMessage = JsonSerializer.Serialize(plan);
|
||||
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
AIAgents.MealAgentId,
|
||||
aiMessage,
|
||||
"createdPlan"
|
||||
);
|
||||
}
|
||||
|
||||
if (messageType == "modifyMealPlan")
|
||||
{
|
||||
var updated = await _mealPlanOrchestrator
|
||||
.UpdatePlanAsync(payload);
|
||||
|
||||
string aiMessage = JsonSerializer.Serialize(updated);
|
||||
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
AIAgents.MealAgentId,
|
||||
aiMessage,
|
||||
"updatedPlan"
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "workoutPlan":
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
userId,
|
||||
message,
|
||||
"userWorkoutReq"
|
||||
);
|
||||
string workoutMessageType = DataExtractor.GetRequiredString(data, "messageType");
|
||||
if (workoutMessageType == "generateWorkoutPlan")
|
||||
{
|
||||
var plan = await _workoutPlanOrchestrator
|
||||
.GeneratePlanAsync(payload);
|
||||
|
||||
string aiMessage = JsonSerializer.Serialize(plan);
|
||||
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
AIAgents.WorkoutAgentId,
|
||||
aiMessage,
|
||||
"createdPlan"
|
||||
);
|
||||
}
|
||||
|
||||
if (workoutMessageType == "modifyWorkoutPlan")
|
||||
{
|
||||
var updated = await _workoutPlanOrchestrator
|
||||
.UpdatePlanAsync(payload);
|
||||
|
||||
string aiMessage = JsonSerializer.Serialize(updated);
|
||||
|
||||
await SendChatMessageAsync(
|
||||
chatId,
|
||||
AIAgents.WorkoutAgentId,
|
||||
aiMessage,
|
||||
"updatedPlan"
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new HubException("Invalid reason for sending message.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task LeaveChat(object payload)
|
||||
{
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
Guid chatId = DataExtractor.GetRequiredGuid(data, "chatId");
|
||||
|
||||
await Groups.RemoveFromGroupAsync(
|
||||
Context.ConnectionId,
|
||||
$"chat-{chatId}"
|
||||
);
|
||||
}
|
||||
|
||||
private async Task SendChatMessageAsync( Guid chatId, Guid senderId, string message,string type)
|
||||
{
|
||||
var savedMessage = await _chatService.SendMessageAsync(new
|
||||
{
|
||||
chatId = chatId,
|
||||
senderId = senderId,
|
||||
message = message,
|
||||
type = type
|
||||
});
|
||||
|
||||
await Clients.Group($"chat-{chatId}")
|
||||
.SendAsync("ReceiveMessage", savedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user