diff --git a/Marco.Pms.Services/Controllers/AttendanceController.cs b/Marco.Pms.Services/Controllers/AttendanceController.cs index 5c7104d..0fbc6b5 100644 --- a/Marco.Pms.Services/Controllers/AttendanceController.cs +++ b/Marco.Pms.Services/Controllers/AttendanceController.cs @@ -7,11 +7,13 @@ using Marco.Pms.Model.Mapper; using Marco.Pms.Model.Projects; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.AttendanceVM; +using Marco.Pms.Services.Hubs; using Marco.Pms.Services.Service; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; using Microsoft.CodeAnalysis; using Microsoft.EntityFrameworkCore; using Document = Marco.Pms.Model.DocumentManager.Document; @@ -30,10 +32,11 @@ namespace MarcoBMS.Services.Controllers private readonly S3UploadService _s3Service; private readonly PermissionServices _permission; private readonly ILoggingService _logger; + private readonly IHubContext _signalR; public AttendanceController( - ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper, S3UploadService s3Service, ILoggingService logger, PermissionServices permission) + ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper, S3UploadService s3Service, ILoggingService logger, PermissionServices permission, IHubContext signalR) { _context = context; _employeeHelper = employeeHelper; @@ -42,6 +45,7 @@ namespace MarcoBMS.Services.Controllers _s3Service = s3Service; _logger = logger; _permission = permission; + _signalR = signalR; } private Guid GetTenantId() @@ -558,6 +562,7 @@ namespace MarcoBMS.Services.Controllers Activity = attendance.Activity, JobRoleName = employee.JobRole.Name }; + await _signalR.Clients.All.SendAsync("Attendance", new { LoggedInUserId = currentEmployee.Id, ProjectId = recordAttendanceDot.ProjectID, Response = vm }); _logger.LogInfo("Attendance for employee {FirstName} {LastName} has been marked", employee.FirstName ?? string.Empty, employee.LastName ?? string.Empty); return Ok(ApiResponse.SuccessResponse(vm, "Attendance marked successfully.", 200)); } diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 3512081..7835e8d 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -749,11 +749,11 @@ namespace Marco.Pms.Services.Controllers return Ok(response); } - [HttpGet("contact-tag/{id}")] - public async Task GetContactTagMaster(Guid id) - { - return Ok(); - } + //[HttpGet("contact-tag/{id}")] + //public async Task GetContactTagMaster(Guid id) + //{ + // return Ok(); + //} [HttpPost("contact-tag")] public async Task CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto) diff --git a/Marco.Pms.Services/Hub/MarcoHub.cs b/Marco.Pms.Services/Hub/MarcoHub.cs new file mode 100644 index 0000000..bf6fc38 --- /dev/null +++ b/Marco.Pms.Services/Hub/MarcoHub.cs @@ -0,0 +1,35 @@ +using MarcoBMS.Services.Service; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; + +namespace Marco.Pms.Services.Hubs +{ + [Authorize] + public class MarcoHub : Hub + { + private readonly ILoggingService _logger; + public MarcoHub(ILoggingService logger) + { + _logger = logger; + } + public async Task SendMessage(string user, string message) + { + _logger.LogInfo($"User: {user} Message : {message}"); + await Clients.All.SendAsync("ReceiveMessage", user, message); + } + public override async Task OnConnectedAsync() + { + await base.OnConnectedAsync(); + _logger.LogInfo($"Connected successfully"); + await Clients.All.SendAsync("Connected successfully"); + } + + // Optional: override OnDisconnectedAsync + public override async Task OnDisconnectedAsync(Exception? exception) + { + await base.OnDisconnectedAsync(exception); + _logger.LogInfo($"DIsonnected successfully"); + await Clients.All.SendAsync("Disonnected successfully"); + } + } +} diff --git a/Marco.Pms.Services/Marco.Pms.Services.csproj b/Marco.Pms.Services/Marco.Pms.Services.csproj index 6482198..7bef32f 100644 --- a/Marco.Pms.Services/Marco.Pms.Services.csproj +++ b/Marco.Pms.Services/Marco.Pms.Services.csproj @@ -17,6 +17,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Marco.Pms.Services/Program.cs b/Marco.Pms.Services/Program.cs index e57fa15..17eb5c7 100644 --- a/Marco.Pms.Services/Program.cs +++ b/Marco.Pms.Services/Program.cs @@ -4,6 +4,7 @@ using Marco.Pms.Model.Authentication; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Utilities; using Marco.Pms.Services.Helpers; +using Marco.Pms.Services.Hubs; using Marco.Pms.Services.Service; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Middleware; @@ -59,7 +60,8 @@ builder.Services.AddCors(options => { policy.AllowAnyOrigin() .AllowAnyMethod() - .AllowAnyHeader(); + .AllowAnyHeader() + .WithExposedHeaders("Authorization"); }); }); @@ -161,10 +163,28 @@ if (jwtSettings != null && jwtSettings.Key != null) ValidAudience = jwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key)) }; + + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Query["access_token"]; + var path = context.HttpContext.Request.Path; + + // Match your hub route here + if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs/marco")) + { + context.Token = accessToken; + } + + return Task.CompletedTask; + } + }; }); builder.Services.AddSingleton(jwtSettings); } +builder.Services.AddSignalR(); builder.WebHost.ConfigureKestrel(options => { options.AddServerHeader = false; // Disable the "Server" header @@ -207,7 +227,7 @@ app.UseHttpsRedirection(); app.UseAuthorization(); - +app.MapHub("/hubs/marco"); app.MapControllers(); app.Run(); diff --git a/Marco.Pms.Services/appsettings.Development.json b/Marco.Pms.Services/appsettings.Development.json index 2cbcbcf..1565018 100644 --- a/Marco.Pms.Services/appsettings.Development.json +++ b/Marco.Pms.Services/appsettings.Development.json @@ -9,7 +9,7 @@ "Title": "Dev" }, "ConnectionStrings": { - "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMSGuid" + "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" }, "SmtpSettings": { "SmtpServer": "smtp.gmail.com",