Prechádzať zdrojové kódy

Chat : list messages

zinab_elgendy 1 mesiac pred
rodič
commit
cb2a74a671

+ 0 - 12
MTWorkHR.API/Chat/ChatHub.cs

@@ -1,12 +0,0 @@
-using Microsoft.AspNetCore.SignalR;
-
-namespace MTWorkHR.API.Chat
-{
-    public class ChatHubxx : Hub
-    {
-        public async Task SendMessage(string user, string message)
-        {
-            await Clients.All.SendAsync("ReceiveMessage", user, message);
-        }
-    }
-}

+ 0 - 7
MTWorkHR.API/Chat/IChatClient.cs

@@ -1,7 +0,0 @@
-namespace MTWorkHR.API.Chat
-{
-    public interface IChatClient
-    {
-        Task ReceiveMessage(string message);
-    }
-}

+ 137 - 52
MTWorkHR.Application/Chat/ChatHub.cs

@@ -1,5 +1,6 @@
 using Microsoft.AspNetCore.Identity;
 using Microsoft.AspNetCore.SignalR;
+using Microsoft.EntityFrameworkCore;
 using MTWorkHR.Application.Filters;
 using MTWorkHR.Application.Identity;
 using MTWorkHR.Application.Mapper;
@@ -11,6 +12,8 @@ using MTWorkHR.Core.Global;
 using MTWorkHR.Core.UnitOfWork;
 using MTWorkHR.Infrastructure.Entities;
 using System;
+using System.Linq.Dynamic.Core.Tokenizer;
+using System.Security.Claims;
 using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
 
 namespace MTWorkHR.API.Chat
@@ -20,100 +23,132 @@ namespace MTWorkHR.API.Chat
     {
         private readonly IUnitOfWork _unitOfWork;
         private readonly GlobalInfo _globalInfo;
-        private readonly UserService _userService; 
-        public ChatHub(IUnitOfWork unitOfWork, GlobalInfo globalInfo, UserService userService) 
+        //private readonly UserService _userService; 
+        private readonly ApplicationUserManager _userManager;
+
+        public ChatHub(IUnitOfWork unitOfWork, GlobalInfo globalInfo, ApplicationUserManager userManager /*, UserService userService*/) 
         {
             _unitOfWork = unitOfWork;
             _globalInfo = globalInfo;
-            _userService = userService;
+            //  _userService = userService;
+            _userManager = userManager;
         }
 
 
-        public async Task authMe()
+       
+        public async Task getCompanyUsersList()
         {
-            string currSignalrID = Context.ConnectionId;
-            //Person tempPerson = ctx.Person.Where(p => p.Username == personInfo.userName && p.Password == personInfo.password)
-            //    .SingleOrDefault();
-
-            if (_globalInfo.UserId != null) //if credentials are correct
-            {
-                Console.WriteLine("\n" + _globalInfo.UserName + " logged in" + "\nSignalrID: " + currSignalrID);
+            var companyUsers = await GetAllCompanyEmployees();
 
-                HubConnection currUser = new HubConnection
-                {
-                    UserId = _globalInfo.UserId,
-                    SignalrId = currSignalrID,
-                    TimeStamp = DateTime.Now
-                };
-                var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser);
-
-                await _unitOfWork.CompleteAsync();
-
-                ChatUserDto newUser = new ChatUserDto(_globalInfo.UserId, _globalInfo.UserName, currSignalrID);
-                await Clients.Caller.SendAsync("authMeResponseSuccess", newUser);//4Tutorial
-                await Clients.Others.SendAsync("userOn", newUser);//4Tutorial
-            }
-
-            else //if credentials are incorrect
-            {
-                await Clients.Caller.SendAsync("authMeResponseFail");
-            }
+            await Clients.Caller.SendAsync("getCompanyUsersList", companyUsers);
         }
 
-      
-      
-        public async Task getCompanyUsersList()
+        public async Task<List<UserAllDto>> GetAllCompanyEmployees()
         {
-            var companyUsers = await _userService.GetAllCompanyEmployees();
-            var response = MapperObject.Mapper.Map<List<UserAllDto>>(companyUsers);
+            var employees = await _userManager.GetUsersInRoleAsync("Employee");
+            var companyId = Context.User.Identities.FirstOrDefault().FindFirst("companyId")?.Value;
+            var CompanyId = long.Parse(companyId);
+            var res = employees.Where(e => e.CompanyId == CompanyId).ToList();
+            var response = MapperObject.Mapper.Map<List<UserAllDto>>(res);
 
-            await Clients.Caller.SendAsync("getCompanyUsersList", response);
+            return response;
         }
 
-      
+
         //Simple Test Method
         public async Task SendMessageAll(string user, string message)
         {
             await Clients.All.SendAsync("ReceiveMessage", user, message);
         }
 
-        public async Task sendMsg(string userId, string msg)
+        public async Task sendMsg(string receiverUserId, string msg)
         {
-            var allConnections = await _unitOfWork.HubConnection.GetAllAsync();
-            var receiverUser = allConnections.Item1.FirstOrDefault(c => c.UserId == userId);
-            var connId = receiverUser != null ? receiverUser.SignalrId : "0";
-            ChatMessage messag = new ChatMessage { Content = msg, ReceiverId = connId, SenderId = _globalInfo.UserId, SenderName = _globalInfo.UserName, IsSeen = false };
-            await Clients.Client(connId).SendAsync("sendMsgResponse", Context.ConnectionId, msg);
+            try
+            {
+                var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+                var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value;
+
+                var allConnections = await _unitOfWork.HubConnection.GetAllAsync();
+                var receiverUser = allConnections.Item1.FirstOrDefault(c => c.UserId == receiverUserId);
+                var receiverconnIdDB = receiverUser != null ? receiverUser.SignalrId : "0";
+                ChatMessage messag = new ChatMessage { Content = msg, ReceiverId = receiverUserId, ReceiverName = receiverUser.UserName ?? "", SenderId = userId, SenderName = userName, IsSeen = false };
+                await _unitOfWork.ChatMessage.AddAsync(messag);
+                await _unitOfWork.CompleteAsync();
+                await Clients.Client(receiverconnIdDB).SendAsync("sendMsgResponse", Context.ConnectionId, msg);
+            }
+            catch (Exception e) { }
         }
 
 
         public async Task getAllMessagesByUser(string senderId)
         {
-            var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(senderId, _globalInfo.UserId);
-            await Clients.Caller.SendAsync("allMessagesResponse", allmessages.Item1);
+            var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+            var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(senderId, userId);
+            // Ensure the query is fully materialized before passing it to SignalR
+            var messagesList = await allmessages.Item1.ToListAsync();
+
+            await Clients.Caller.SendAsync("getAllMessagesByUserResponse", messagesList);
         }
 
-        public async override Task<Task> OnDisconnectedAsync(Exception exception)
+        public async override Task OnDisconnectedAsync(Exception exception)
         {
+            var email = Context.User?.FindFirst(ClaimTypes.Email)?.Value;
             var connections = await _unitOfWork.HubConnection.GetAllAsync(Context.ConnectionId);
-           var currUserId = connections.Item1.Select(c => c.UserId).SingleOrDefault();
-            _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList());
-            _unitOfWork.CompleteAsync();
+            var currUserId = connections.Item1.Select(c => c.UserId).SingleOrDefault();
+            await _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList());
+            await _unitOfWork.CompleteAsync();
             await Clients.Others.SendAsync("userOff", currUserId);
-            return base.OnDisconnectedAsync(exception);
+            await base.OnDisconnectedAsync(exception);
         }
+        public override async Task OnConnectedAsync()
+        {
+            try
+            {
+                string currSignalrID = Context.ConnectionId;
+                var email = Context.User?.FindFirst(ClaimTypes.Email)?.Value;
+                var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+                var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value;
 
+                if (userId != null) //if credentials are correct
+                {
+                    HubConnection currUser = new HubConnection
+                    {
+                        UserId = userId,
+                        UserName = userName,
+                        SignalrId = currSignalrID,
+                        TimeStamp = DateTime.Now
+                    };
+                    var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser);
+
+                    await _unitOfWork.CompleteAsync();
+
+                    ChatUserDto newUser = new ChatUserDto(userId, userName, currSignalrID);
+                    await Clients.Caller.SendAsync("authMeResponseSuccess", newUser);//4Tutorial
+                    await Clients.Others.SendAsync("userOn", newUser);//4Tutorial
+                }
+
+                else //if credentials are incorrect
+                {
+                    await Clients.Caller.SendAsync("authMeResponseFail");
+                }
+            }
+            catch (Exception ex) { }
+
+            await base.OnConnectedAsync();
+        }
 
       
-        public void logOut(Guid personId)
+
+        public void logOut(string userId)
         {
+            var userIdAuth = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
             var connections = _unitOfWork.HubConnection.GetAllAsync(Context.ConnectionId).Result;
            // var currUserId = connections.Item1.Select(c => c.UserId).SingleOrDefault();
             _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList());
             _unitOfWork.CompleteAsync();
 
             Clients.Caller.SendAsync("logoutResponse");
-            Clients.Others.SendAsync("userOff", personId);
+            Clients.Others.SendAsync("userOff", userIdAuth);
         }
 
       
@@ -132,6 +167,49 @@ namespace MTWorkHR.API.Chat
             await Clients.Caller.SendAsync("getOnlineUsersResponse", onlineUsers);
         }
 
+        public async Task authMe(PersonalInfo person)
+        {
+            try
+            {
+                string currSignalrID = Context.ConnectionId;
+                //Person tempPerson = ctx.Person.Where(p => p.Username == personInfo.userName && p.Password == personInfo.password)
+                //    .SingleOrDefault();
+                var companyId = Context.User.Identities.FirstOrDefault().FindFirst("companyId")?.Value;
+                var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value;
+                var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value;
+
+                if (userId != null) //if credentials are correct
+                {
+                    Console.WriteLine("\n" + userName + " logged in" + "\nSignalrID: " + currSignalrID);
+
+                    HubConnection currUser = new HubConnection
+                    {
+                        UserId = userId,
+                        UserName = userName,
+                        SignalrId = currSignalrID,
+                        TimeStamp = DateTime.Now
+                    };
+                    var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser);
+
+                    await _unitOfWork.CompleteAsync();
+
+                    ChatUserDto newUser = new ChatUserDto(userId, userName, currSignalrID);
+                    await Clients.Caller.SendAsync("authMeResponseSuccess", newUser);//4Tutorial
+                    await Clients.Others.SendAsync("userOn", newUser);//4Tutorial
+                }
+
+                else //if credentials are incorrect
+                {
+                    await Clients.Caller.SendAsync("authMeResponseFail");
+                }
+            }
+            catch (Exception e)
+            {
+                await Clients.Caller.SendAsync("authMeResponseFail");
+            }
+        }
+
+
 
 
         //public async Task reauthMe(string userId)
@@ -163,4 +241,11 @@ namespace MTWorkHR.API.Chat
 
 
     }
+
+    public class PersonalInfo
+    {
+        public string userName { get; set; }
+        public string password { get; set; }
+        public string userId { get; set; }
+    }
 }

+ 24 - 0
MTWorkHR.Application/Dtos/User/ChatMessageDto.cs

@@ -0,0 +1,24 @@
+using MTWorkHR.Core.Entities.Base;
+using MTWorkHR.Core.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Application.Models
+{
+    public class ChatMessageDto 
+    {
+
+        public string SenderId { get; set; }
+        public string SenderName { get; set; }
+        public string ReceiverId { get; set; }
+        public string ReceiverName { get; set; }
+        public string Content { get; set; }
+        public bool IsSeen { get; set; }
+        public List<ChatAttachment>? ChatAttachments { get; set; }
+
+
+    }
+}

+ 2 - 1
MTWorkHR.Application/Mapper/MappingProfile.cs

@@ -130,7 +130,8 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<CompanyUserDto, ApplicationUser>().ForMember(m => m.UserName, o => o.MapFrom(s => s.Email));
             CreateMap<ApplicationUser, CompanyUserDto>().ForMember(m => m.Password, op => op.Ignore());
             CreateMap<UserTaskStatus, UserTaskStatusDto>().ReverseMap();
-
+            CreateMap<ChatMessageDto, ChatMessage>().ReverseMap();
+            
         }
     }
 }

+ 25 - 5
MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs

@@ -19,6 +19,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using MTWorkHR.Infrastructure.Entities;
+using Microsoft.Extensions.Options;
 
 namespace MTWorkHR.Infrastructure
 {
@@ -37,11 +38,15 @@ namespace MTWorkHR.Infrastructure
             services.AddIdentity<ApplicationUser, ApplicationRole>().AddEntityFrameworkStores<HRDataContext>().AddDefaultTokenProviders();
 
            
-            services.AddAuthentication(options => {
-                 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; // "bearer"
-                 options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 
-            }).AddJwtBearer(o=> o.TokenValidationParameters = new TokenValidationParameters 
+            services.AddAuthentication(options =>
+            {
+                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+            })
+            .AddJwtBearer(options =>
+            {
+                options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateIssuerSigningKey = true,
                     ValidateIssuer = true,
@@ -51,8 +56,23 @@ namespace MTWorkHR.Infrastructure
                     ValidIssuer = config.JwtSettings.Issuer,
                     ValidAudience = config.JwtSettings.Audience,
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.JwtSettings.SecretKey))
-                }) ;
+                };
 
+                // This is the important part to allow SignalR to work with JWT tokens
+                options.Events = new JwtBearerEvents
+                {
+                    OnMessageReceived = context =>
+                    {
+                        var accessToken = context.Request.Query["access_token"];
+                        if (!string.IsNullOrEmpty(accessToken) &&
+                            (context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
+                        {
+                            context.Token = accessToken;
+                        }
+                        return Task.CompletedTask;
+                    }
+                };
+            });
 
 
             services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 3650 - 0
MTWorkHR.Infrastructure/Migrations/20241008101202_addHubConnection.Designer.cs


+ 38 - 0
MTWorkHR.Infrastructure/Migrations/20241008101202_addHubConnection.cs

@@ -0,0 +1,38 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class addHubConnection : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "HubConnections",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    UserId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    UserName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    SignalrId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    TimeStamp = table.Column<DateTime>(type: "datetime2", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_HubConnections", x => x.Id);
+                });
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "HubConnections");
+        }
+    }
+}

+ 26 - 0
MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs

@@ -604,6 +604,32 @@ namespace MTWorkHR.Infrastructure.Migrations
                     b.ToTable("FileLogs");
                 });
 
+            modelBuilder.Entity("MTWorkHR.Core.Entities.HubConnection", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("SignalrId")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<DateTime>("TimeStamp")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("UserId")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserName")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("HubConnections");
+                });
+
             modelBuilder.Entity("MTWorkHR.Core.Entities.Industry", b =>
                 {
                     b.Property<long>("Id")