mirror of
https://github.com/Stone-Red-Code/EchoHub.git
synced 2026-09-06 15:56:19 +02:00
feat: Refactor authentication and token management
- Updated EchoHubConnection to use ApiClient for token retrieval. - Introduced ValidationConstants for common validation patterns and limits. - Enhanced AuthDtos with refresh token support and expiration details. - Added new ChatDtos for channel creation and topic updates. - Created CommonDtos for error and paginated responses. - Implemented RefreshToken model for managing refresh tokens. - Modified JwtTokenService to generate and hash refresh tokens. - Updated AuthController to handle registration, login, token refresh, and logout with improved error handling. - Enhanced ChannelsController with channel creation, topic updates, and pagination for channel retrieval. - Added FilesController for file management with rate limiting. - Improved UsersController for profile updates and avatar uploads with validation. - Integrated rate limiting across controllers to manage request load. - Introduced FileValidationHelper for validating uploaded image files. - Updated database context to include RefreshToken and enforce unique constraints. - Enhanced ChatHub for improved channel and message handling with validation. - Updated Program.cs to configure rate limiting and CORS policies.
This commit is contained in:
@@ -41,8 +41,6 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
// Capture channels before disconnecting, since UserDisconnected clears them
|
||||
// when the last connection for a user is removed.
|
||||
var preDisconnectUsername = Context.User?.FindFirstValue("username");
|
||||
var channelsBeforeDisconnect = preDisconnectUsername is not null
|
||||
? presenceTracker.GetChannelsForUser(preDisconnectUsername)
|
||||
@@ -82,21 +80,18 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
{
|
||||
channelName = channelName.ToLowerInvariant().Trim();
|
||||
|
||||
if (!ValidationConstants.ChannelNameRegex().IsMatch(channelName))
|
||||
{
|
||||
await Clients.Caller.Error("Invalid channel name. Use 2-100 characters: letters, digits, underscores, or hyphens.");
|
||||
return [];
|
||||
}
|
||||
|
||||
var channel = await db.Channels.FirstOrDefaultAsync(c => c.Name == channelName);
|
||||
|
||||
if (channel is null)
|
||||
{
|
||||
channel = new Channel
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = channelName,
|
||||
CreatedByUserId = CurrentUserId,
|
||||
};
|
||||
|
||||
db.Channels.Add(channel);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
logger.LogInformation("Channel '{Channel}' created by {User}", channelName, CurrentUsername);
|
||||
await Clients.Caller.Error($"Channel '{channelName}' does not exist. Create it first via the channel list.");
|
||||
return [];
|
||||
}
|
||||
|
||||
presenceTracker.JoinChannel(CurrentUsername, channelName);
|
||||
@@ -126,6 +121,12 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
{
|
||||
channelName = channelName.ToLowerInvariant().Trim();
|
||||
|
||||
if (!ValidationConstants.ChannelNameRegex().IsMatch(channelName))
|
||||
{
|
||||
await Clients.Caller.Error("Invalid channel name.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
await Clients.Caller.Error("Message content cannot be empty.");
|
||||
@@ -181,13 +182,12 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
public async Task<List<MessageDto>> GetChannelHistory(string channelName, int count = HubConstants.DefaultHistoryCount)
|
||||
{
|
||||
channelName = channelName.ToLowerInvariant().Trim();
|
||||
count = Math.Clamp(count, 1, ValidationConstants.MaxHistoryCount);
|
||||
|
||||
var channel = await db.Channels.FirstOrDefaultAsync(c => c.Name == channelName);
|
||||
|
||||
if (channel is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var messages = await db.Messages
|
||||
.Where(m => m.ChannelId == channel.Id)
|
||||
@@ -214,6 +214,12 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
|
||||
public async Task UpdateStatus(UserStatus status, string? statusMessage)
|
||||
{
|
||||
if (statusMessage is not null && statusMessage.Length > ValidationConstants.MaxStatusMessageLength)
|
||||
{
|
||||
await Clients.Caller.Error($"Status message must not exceed {ValidationConstants.MaxStatusMessageLength} characters.");
|
||||
return;
|
||||
}
|
||||
|
||||
var user = await db.Users.FindAsync(CurrentUserId);
|
||||
|
||||
if (user is null)
|
||||
@@ -223,7 +229,7 @@ public class ChatHub(EchoHubDbContext db, ILogger<ChatHub> logger, PresenceTrack
|
||||
}
|
||||
|
||||
user.Status = status;
|
||||
user.StatusMessage = statusMessage;
|
||||
user.StatusMessage = statusMessage?.Trim();
|
||||
user.LastSeenAt = DateTimeOffset.UtcNow;
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user