Files
ClubPenguinServer/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs
rootdarkarchon d37c1208fe Adjust Auth on server (#15)
* add auth that verifies identity is marked online

* few changes for testing

* handle identity with requirements

* remove unnecessary logging from auth handler

* change to UserRequirements

* fixes to checks

* fixes to UserRequirementHandler

Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
2022-10-10 19:44:30 +02:00

156 lines
6.4 KiB
C#

using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using MareSynchronos.API;
using MareSynchronosServer.Services;
using MareSynchronosServer.Utils;
using MareSynchronosShared.Authentication;
using MareSynchronosShared.Data;
using MareSynchronosShared.Metrics;
using MareSynchronosShared.Protos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace MareSynchronosServer.Hubs;
[Authorize]
public partial class MareHub : Hub<IMareHub>, IMareHub
{
private readonly MareMetrics _mareMetrics;
private readonly AuthService.AuthServiceClient _authServiceClient;
private readonly FileService.FileServiceClient _fileServiceClient;
private readonly SystemInfoService _systemInfoService;
private readonly IHttpContextAccessor _contextAccessor;
private readonly GrpcClientIdentificationService _clientIdentService;
private readonly MareHubLogger _logger;
private readonly MareDbContext _dbContext;
private readonly Uri _cdnFullUri;
private readonly string _shardName;
private readonly int _maxExistingGroupsByUser;
private readonly int _maxJoinedGroupsByUser;
private readonly int _maxGroupUserCount;
public MareHub(MareMetrics mareMetrics, AuthService.AuthServiceClient authServiceClient, FileService.FileServiceClient fileServiceClient,
MareDbContext mareDbContext, ILogger<MareHub> logger, SystemInfoService systemInfoService, IConfiguration configuration, IHttpContextAccessor contextAccessor,
GrpcClientIdentificationService clientIdentService)
{
_mareMetrics = mareMetrics;
_authServiceClient = authServiceClient;
_fileServiceClient = fileServiceClient;
_systemInfoService = systemInfoService;
var config = configuration.GetRequiredSection("MareSynchronos");
_cdnFullUri = new Uri(config.GetValue<string>("CdnFullUrl"));
_shardName = config.GetValue("ShardName", "Main");
_maxExistingGroupsByUser = config.GetValue<int>("MaxExistingGroupsByUser", 3);
_maxJoinedGroupsByUser = config.GetValue<int>("MaxJoinedGroupsByUser", 6);
_maxGroupUserCount = config.GetValue<int>("MaxGroupUserCount", 100);
_contextAccessor = contextAccessor;
_clientIdentService = clientIdentService;
_logger = new MareHubLogger(this, logger);
_dbContext = mareDbContext;
}
[Authorize(Policy = "Authenticated")]
public async Task<ConnectionDto> Heartbeat(string characterIdentification)
{
_mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections);
var userId = Context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value;
_logger.LogCallInfo(MareHubLogger.Args(characterIdentification));
await Clients.Caller.Client_UpdateSystemInfo(_systemInfoService.SystemInfoDto).ConfigureAwait(false);
var isBanned = await _dbContext.BannedUsers.AsNoTracking().AnyAsync(u => u.CharacterIdentification == characterIdentification).ConfigureAwait(false);
if (!string.IsNullOrEmpty(userId) && !isBanned && !string.IsNullOrEmpty(characterIdentification))
{
var user = (await _dbContext.Users.SingleAsync(u => u.UID == userId).ConfigureAwait(false));
var existingIdent = _clientIdentService.GetCharacterIdentForUid(userId);
if (!string.IsNullOrEmpty(existingIdent) && !string.Equals(characterIdentification, existingIdent, StringComparison.Ordinal))
{
_logger.LogCallWarning(MareHubLogger.Args(characterIdentification, "Failure", "LoggedIn"));
return new ConnectionDto()
{
ServerVersion = IMareHub.ApiVersion
};
}
user.LastLoggedIn = DateTime.UtcNow;
_clientIdentService.MarkUserOnline(user.UID, characterIdentification);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
_logger.LogCallInfo(MareHubLogger.Args(characterIdentification, "Success"));
return new ConnectionDto
{
ServerVersion = IMareHub.ApiVersion,
UID = string.IsNullOrEmpty(user.Alias) ? user.UID : user.Alias,
IsModerator = user.IsModerator,
IsAdmin = user.IsAdmin,
ServerInfo = new ServerInfoDto()
{
MaxGroupsCreatedByUser = _maxExistingGroupsByUser,
ShardName = _shardName,
MaxGroupsJoinedByUser = _maxJoinedGroupsByUser,
MaxGroupUserCount = _maxGroupUserCount
}
};
}
_logger.LogCallWarning(MareHubLogger.Args(characterIdentification, "Failure"));
return new ConnectionDto()
{
ServerVersion = IMareHub.ApiVersion
};
}
[Authorize(Policy = "Authenticated")]
public async Task<bool> CheckClientHealth()
{
var needsReconnect = !_clientIdentService.IsOnCurrentServer(AuthenticatedUserId);
if (needsReconnect)
{
_logger.LogCallWarning(MareHubLogger.Args(needsReconnect));
}
return needsReconnect;
}
public override async Task OnConnectedAsync()
{
_logger.LogCallInfo(MareHubLogger.Args(_contextAccessor.GetIpAddress()));
_mareMetrics.IncGauge(MetricsAPI.GaugeConnections);
await base.OnConnectedAsync().ConfigureAwait(false);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
_mareMetrics.DecGauge(MetricsAPI.GaugeConnections);
var userCharaIdent = _clientIdentService.GetCharacterIdentForUid(AuthenticatedUserId);
if (!string.IsNullOrEmpty(userCharaIdent))
{
_mareMetrics.DecGauge(MetricsAPI.GaugeAuthorizedConnections);
_logger.LogCallInfo();
await SendOfflineToAllPairedUsers(userCharaIdent).ConfigureAwait(false);
_dbContext.RemoveRange(_dbContext.Files.Where(f => !f.Uploaded && f.UploaderUID == AuthenticatedUserId));
_clientIdentService.MarkUserOffline(AuthenticatedUserId);
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
}
await base.OnDisconnectedAsync(exception).ConfigureAwait(false);
}
}