Skip to content

Commit fa93b4c

Browse files
committed
refactor: resolve SonarQube code quality issues
- Add JWT key validation with null-check and minimum length requirement - Fix Entity operator== to use ReferenceEquals for null comparison - Seal HomeController and add route prefix + ProducesResponseType - Replace Any() with Count comparisons for clarity and performance - Convert constant arrays to static readonly fields - Rename UserPasswordUpdateDTO to UserPasswordUpdateDto (naming convention) - Remove unused private setters from Event model - Remove TODO comments from placeholder controller methods
1 parent 86cae16 commit fa93b4c

15 files changed

Lines changed: 41 additions & 25 deletions

File tree

EventFlow.Application/Behaviors/ValidationBehavior.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public async Task<TResponse> Handle(
1818
RequestHandlerDelegate<TResponse> next,
1919
CancellationToken cancellationToken)
2020
{
21-
if (!_validators.Any())
21+
if (_validators is ICollection<IValidator<TRequest>> validatorCollection
22+
? validatorCollection.Count == 0
23+
: !_validators.Any())
2224
{
2325
return await next();
2426
}
@@ -32,7 +34,7 @@ public async Task<TResponse> Handle(
3234
.Where(f => f != null)
3335
.ToList();
3436

35-
if (failures.Any())
37+
if (failures.Count > 0)
3638
{
3739
throw new ValidationException(failures);
3840
}

EventFlow.Application/DTOs/UserPasswordUpdateDTO.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace EventFlow.Application.DTOs;
22

3-
public class UserPasswordUpdateDTO
3+
public class UserPasswordUpdateDto
44
{
55
public string CurrentPassword { get; set; } = string.Empty;
66
public string NewPassword { get; set; } = string.Empty;

EventFlow.Application/Services/AuthService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public class AuthService(
5757
};
5858
}
5959

60-
public async Task<bool> UpdatePasswordAsync(ClaimsPrincipal userClaims, UserPasswordUpdateDTO dto)
60+
public async Task<bool> UpdatePasswordAsync(ClaimsPrincipal userClaims, UserPasswordUpdateDto dto)
6161
{
6262
var email = userClaims.FindFirstValue(ClaimTypes.Email);
6363
if (string.IsNullOrEmpty(email)) return false;

EventFlow.Application/Services/IAuthService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ public interface IAuthService
77
Task<UserDTO?> RegisterAsync(RegisterUserCommand command);
88
Task<string?> LoginAsync(LoginUserCommand command);
99
Task<UserDTO?> GetAuthenticatedUserAsync(ClaimsPrincipal user);
10-
Task<bool> UpdatePasswordAsync(ClaimsPrincipal user, UserPasswordUpdateDTO dto);
10+
Task<bool> UpdatePasswordAsync(ClaimsPrincipal user, UserPasswordUpdateDto dto);
1111
}

EventFlow.Application/Services/RecommendationService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ public async Task<IEnumerable<EventDTO>> GetRecommendedEventsAsync(int participa
1414
? participantWithEvents.Events.Select(e => e.Id).ToHashSet()
1515
: new HashSet<int>();
1616

17-
if (!participantEventsIds.Any())
17+
if (participantEventsIds.Count == 0)
1818
{
1919
return Enumerable.Empty<EventDTO>();
2020
}
2121

2222
var allParticipants = await _participantRepository.GetAllParticipantsWithEventsAsync();
2323
var similarParticipants = allParticipants
24-
.Where(p => p.Id != participantId && (p.Events?.Any(e => participantEventsIds.Contains(e.Id)) ?? false))
24+
.Where(p => p.Id != participantId && p.Events != null && p.Events.Count(e => participantEventsIds.Contains(e.Id)) > 0)
2525
.ToList();
2626

2727
var recommendedEvents = similarParticipants
@@ -42,7 +42,7 @@ public async Task<IEnumerable<object>> GetRecommendedConnectionsAsync(int partic
4242
? participantWithEvents.Events.Select(e => e.Id).ToHashSet()
4343
: new HashSet<int>();
4444

45-
if (!participantEventsIds.Any())
45+
if (participantEventsIds.Count == 0)
4646
{
4747
return Enumerable.Empty<object>();
4848
}

EventFlow.Core/Models/Event.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ public class Event : Entity<int>
77
public DateTime Date { get; private set; }
88
public EventLocation Location { get; private set; } = null!;
99
public int OrganizerId { get; private set; }
10-
public Organizer? Organizer { get; private set; }
11-
public string? Category { get; private set; }
10+
public Organizer? Organizer { get; init; }
11+
public string? Category { get; init; }
1212
public ICollection<SpeakerEvent> SpeakerEvents { get; private set; } = [];
1313
public ICollection<Participant> Participants { get; private set; } = [];
1414
public DateTime CreatedAt { get; private set; }

EventFlow.Core/Primitives/Entity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public override int GetHashCode()
5050

5151
public static bool operator ==(Entity<TId>? a, Entity<TId>? b)
5252
{
53-
if (a is null && b is null)
53+
if (ReferenceEquals(a, b))
5454
return true;
5555

5656
if (a is null || b is null)

EventFlow.Infrastructure/Data/EventFlowContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public override async Task<int> SaveChangesAsync(CancellationToken cancellationT
4949

5050
var result = await base.SaveChangesAsync(cancellationToken);
5151

52-
if (_domainEventDispatcher != null && domainEvents.Any())
52+
if (_domainEventDispatcher != null && domainEvents.Count > 0)
5353
{
5454
await _domainEventDispatcher.DispatchAsync(domainEvents, cancellationToken);
5555
}

EventFlow.Infrastructure/Services/JwtTokenService.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ public JwtTokenService(IConfiguration configuration)
1919
public string GenerateToken(int userId, string username, string email)
2020
{
2121
var tokenHandler = new JwtSecurityTokenHandler();
22-
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]!);
22+
var jwtKey = _configuration["Jwt:Key"]
23+
?? throw new InvalidOperationException("JWT Key is not configured.");
24+
25+
if (jwtKey.Length < 32)
26+
throw new InvalidOperationException("JWT Key must be at least 32 characters long.");
27+
28+
var key = Encoding.ASCII.GetBytes(jwtKey);
2329

2430
var tokenDescriptor = new SecurityTokenDescriptor
2531
{
@@ -45,7 +51,13 @@ public string GenerateToken(int userId, string username, string email)
4551
public ClaimsPrincipal? ValidateToken(string token)
4652
{
4753
var tokenHandler = new JwtSecurityTokenHandler();
48-
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]!);
54+
var jwtKey = _configuration["Jwt:Key"]
55+
?? throw new InvalidOperationException("JWT Key is not configured.");
56+
57+
if (jwtKey.Length < 32)
58+
throw new InvalidOperationException("JWT Key must be at least 32 characters long.");
59+
60+
var key = Encoding.ASCII.GetBytes(jwtKey);
4961

5062
try
5163
{

EventFlow.Presentation/Config/AppConfiguration.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,14 @@ public static IServiceCollection AddRateLimitingConfig(this IServiceCollection s
118118
return services;
119119
}
120120

121+
private static readonly string[] DatabaseHealthTags = ["db", "sql"];
122+
private static readonly string[] RedisHealthTags = ["cache", "redis"];
123+
121124
public static IServiceCollection AddHealthCheckConfig(this IServiceCollection services, IConfiguration configuration)
122125
{
123126
services.AddHealthChecks()
124-
.AddDbContextCheck<EventFlowContext>("database", failureStatus: Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Unhealthy, tags: new[] { "db", "sql" })
125-
.AddRedis("redis", failureStatus: Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Degraded, tags: new[] { "cache", "redis" });
127+
.AddDbContextCheck<EventFlowContext>("database", failureStatus: Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Unhealthy, tags: DatabaseHealthTags)
128+
.AddRedis("redis", failureStatus: Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Degraded, tags: RedisHealthTags);
126129

127130
services.AddHealthChecksUI(options =>
128131
{

0 commit comments

Comments
 (0)