diff --git a/src/Services/Identity/Identity.API/Services/UserGrpcService.cs b/src/Services/Identity/Identity.API/Services/UserGrpcService.cs index 2688f4e92..051095a6b 100644 --- a/src/Services/Identity/Identity.API/Services/UserGrpcService.cs +++ b/src/Services/Identity/Identity.API/Services/UserGrpcService.cs @@ -432,8 +432,8 @@ ServerCallContext context result.Data.Select(user => new GrpcUserResponse { UserId = user.Sub, - FirstName = user.GivenName ?? "", - LastName = user.FamilyName ?? "", + FirstName = user.FirstName ?? "", + LastName = user.LastName ?? "", UserName = user.UserName ?? "", Email = user.Email, ImageUrl = user.Picture, diff --git a/src/Services/Identity/Identity.Application/Commands/BulkProvisioning/AcceptInvitation/AcceptInvitationCommandHandler.cs b/src/Services/Identity/Identity.Application/Commands/BulkProvisioning/AcceptInvitation/AcceptInvitationCommandHandler.cs index 86d280a1d..e8a6c39a9 100644 --- a/src/Services/Identity/Identity.Application/Commands/BulkProvisioning/AcceptInvitation/AcceptInvitationCommandHandler.cs +++ b/src/Services/Identity/Identity.Application/Commands/BulkProvisioning/AcceptInvitation/AcceptInvitationCommandHandler.cs @@ -216,8 +216,8 @@ public async Task Handle( orgUser.Id, user.Id); } - // 10. Activate user (Pending -> Active) and confirm email - if (user.Status == UserStatus.Pending) + // 10. Activate user (if not already Active or Deleted) + if (user.Status != UserStatus.Active && user.Status != UserStatus.Deleted) { user.Activate(); } diff --git a/src/Services/Identity/Identity.Application/Users/Queries/GetOrganizationUsersByOrganizationId/GetOrganizationUsersByOrganizationIdQueryHandler.cs b/src/Services/Identity/Identity.Application/Users/Queries/GetOrganizationUsersByOrganizationId/GetOrganizationUsersByOrganizationIdQueryHandler.cs index bb7e9d9fe..36a1d58c1 100644 --- a/src/Services/Identity/Identity.Application/Users/Queries/GetOrganizationUsersByOrganizationId/GetOrganizationUsersByOrganizationIdQueryHandler.cs +++ b/src/Services/Identity/Identity.Application/Users/Queries/GetOrganizationUsersByOrganizationId/GetOrganizationUsersByOrganizationIdQueryHandler.cs @@ -49,20 +49,21 @@ public async Task> Handle( try { - var (userIds, totalUniqueUsers) = await _organizationUserRepository.GetDistinctUserIdsByOrganizationAsync( + // Fetch all distinct user ids first so filters can be applied before paging + var (allUserIds, totalDistinctUsers) = await _organizationUserRepository.GetDistinctUserIdsByOrganizationAsync( request.OrganizationId, request.ActiveOnly, - request.PageNumber, - request.PageSize, + pageNumber: 1, + pageSize: int.MaxValue, cancellationToken); _logger.LogInformation( "Retrieved {UserCount} distinct user IDs for organization {OrganizationId}. Total unique users: {TotalUniqueUsers}", - userIds.Count, + allUserIds.Count, request.OrganizationId, - totalUniqueUsers); + totalDistinctUsers); - if (userIds.Count == 0) + if (allUserIds.Count == 0) { _logger.LogInformation( "No users found for organization {OrganizationId} with ActiveOnly={ActiveOnly}. Returning empty result.", @@ -70,21 +71,21 @@ public async Task> Handle( request.ActiveOnly); return new PagedResult( Enumerable.Empty(), - totalUniqueUsers, + 0, request.PageNumber, request.PageSize); } var organizationUsers = await _organizationUserRepository.GetSubscriptionsForUsersAsync( request.OrganizationId, - userIds, + allUserIds, request.ActiveOnly, cancellationToken); _logger.LogInformation( "Retrieved {OrgUserCount} organization users for {UserCount} users in organization {OrganizationId}", organizationUsers.Count, - userIds.Count, + allUserIds.Count, request.OrganizationId); if (!string.IsNullOrWhiteSpace(request.Role)) @@ -154,7 +155,7 @@ public async Task> Handle( var groupId = request.GroupId.Value; var beforeCount = organizationUsers.Count; organizationUsers = organizationUsers - .Where(ou => ou.GroupId == groupId) + .Where(ou => groupId == 0 ? ou.GroupId == null : ou.GroupId == groupId) .ToList(); _logger.LogInformation( @@ -310,17 +311,23 @@ public async Task> Handle( .ThenBy(u => u.Email) .ToList(); + var filteredTotalUsers = groupedByUser.Count; + var pagedUsers = groupedByUser + .Skip((request.PageNumber - 1) * request.PageSize) + .Take(request.PageSize) + .ToList(); + _logger.LogInformation( - "Successfully processed query for organization {OrganizationId}. Returning {ResultCount} users (grouped), TotalUniqueUsers: {TotalUniqueUsers}, PageNumber: {PageNumber}, PageSize: {PageSize}", + "Successfully processed query for organization {OrganizationId}. Returning {ResultCount} users (grouped) after paging, FilteredTotalUsers: {FilteredTotalUsers}, PageNumber: {PageNumber}, PageSize: {PageSize}", request.OrganizationId, - groupedByUser.Count, - totalUniqueUsers, + pagedUsers.Count, + filteredTotalUsers, request.PageNumber, request.PageSize); return new PagedResult( - groupedByUser, - totalUniqueUsers, + pagedUsers, + filteredTotalUsers, request.PageNumber, request.PageSize); } diff --git a/src/Services/Identity/Identity.Web/Controllers/AccountController.cs b/src/Services/Identity/Identity.Web/Controllers/AccountController.cs index 43376c198..0e073e449 100644 --- a/src/Services/Identity/Identity.Web/Controllers/AccountController.cs +++ b/src/Services/Identity/Identity.Web/Controllers/AccountController.cs @@ -180,13 +180,20 @@ public async Task Logout(string? returnUrl = null, string? mode = await HttpContext.SignOutAsync(IdentityConstants.TwoFactorUserIdScheme); + var isSecureRequest = Request.IsHttps || + string.Equals( + Request.Headers["X-Forwarded-Proto"], + "https", + StringComparison.OrdinalIgnoreCase); + var cookieOptions = new CookieOptions { HttpOnly = true, SameSite = SameSiteMode.None, - Secure = Request.IsHttps, + Secure = true, Path = "/", - Expires = DateTimeOffset.UtcNow.AddYears(-1) + Expires = DateTimeOffset.UtcNow.AddYears(-1), + Domain = isSecureRequest ? Request.Host.Host : null }; Response.Cookies.Delete(".AspNetCore.Identity.Application", cookieOptions); diff --git a/src/Services/STEMify-Backend/STEMify-Backend.AppHost/infra/notification-api.tmpl.yaml b/src/Services/STEMify-Backend/STEMify-Backend.AppHost/infra/notification-api.tmpl.yaml index 1cd6af5a2..d9fdeacb2 100644 --- a/src/Services/STEMify-Backend/STEMify-Backend.AppHost/infra/notification-api.tmpl.yaml +++ b/src/Services/STEMify-Backend/STEMify-Backend.AppHost/infra/notification-api.tmpl.yaml @@ -71,9 +71,9 @@ properties: - name: ClientApp value: {{ if .Env.CLIENT_APP_URL }}{{ .Env.CLIENT_APP_URL }}{{ else }}https://localhost:3000{{ end }} - name: Issuer - value: https://identity-api.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}/ + value: https://identity.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}/ - name: IdentityServiceUrl - value: https://identity-api.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }} + value: https://identity.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }} scale: minReplicas: 1 tags: