private async Task RemoveParticipant(Participant participant, string?connectionId, CancellationToken cancellationToken) { _logger.LogDebug("RemoveParticipant() | {participant}, connectionId:{connectionId}", participant, connectionId); if (connectionId == null) { if (!_connections.TryGetParticipant(participant.Id, out var connection)) { return; } connectionId = connection.ConnectionId; } if (_connections.TryRemoveParticipant(participant.Id, new ParticipantConnection(participant.ConferenceId, connectionId))) { _logger.LogDebug("Remove participant connection"); await _hubContext.Groups.RemoveFromGroupAsync(connectionId, CoreHubGroups.OfParticipant(participant), cancellationToken); await _hubContext.Groups.RemoveFromGroupAsync(connectionId, CoreHubGroups.OfConference(participant.ConferenceId), cancellationToken); if (await _repository.IsParticipantJoined(participant, connectionId)) { await using var @lock = await _repository.LockParticipantJoin(participant); if (await _repository.IsParticipantJoined(participant, connectionId)) { await _mediator.Publish(new ParticipantLeftNotification(participant, connectionId), @lock.HandleLostToken); } } else { _logger.LogDebug("Participant is not joined"); } } else { _logger.LogDebug("Participant connection was already removed"); } }
public async Task <Unit> Handle(UpdateSubscriptionsRequest request, CancellationToken cancellationToken) { var participant = request.Participant; _logger.LogDebug("Update subscriptions for {participant}", participant); var subscriptions = new HashSet <SynchronizedObjectId>(); foreach (var provider in _providers) { var availableSubscriptions = await provider.GetAvailableObjects(participant); subscriptions.UnionWith(availableSubscriptions); } _logger.LogDebug("Add {count} subscriptions", subscriptions.Count); var oldSubscriptions = await _subscriptionsRepository.GetSet(participant, subscriptions.Select(x => x.ToString()).ToList()) ?? ImmutableList <string> .Empty; if (!await _joinedParticipantsRepository.IsParticipantJoined(participant)) { _logger.LogWarning("The participant does not seem to be joined, remove all subscriptions"); await _subscriptionsRepository.Remove(participant); return(Unit.Value); } var added = subscriptions.Where(x => !oldSubscriptions.Contains(x.ToString())).ToList(); await SendCurrentSynchronizedObjectValues(participant, added); var removed = oldSubscriptions.Except(subscriptions.Select(x => x.ToString())) .Select(SynchronizedObjectId.Parse).ToList(); if (removed.Any() || added.Any()) { await _mediator.Publish(new ParticipantSubscriptionsUpdatedNotification(participant, removed, added)); } return(Unit.Value); }
public async Task <Unit> Handle(UpdateParticipantsPermissionsRequest request, CancellationToken cancellationToken) { var participants = request.Participants; var newPermissions = new Dictionary <Participant, PermissionsDict>(); foreach (var participant in participants) { newPermissions.Add(participant, await _permissionLayersAggregator.FetchAggregatedPermissions(participant)); cancellationToken.ThrowIfCancellationRequested(); } _logger.LogDebug("Update permissions for {count} participants", newPermissions.Count); var appliedPermissions = new Dictionary <Participant, PermissionsDict>(); foreach (var(participant, permissions) in newPermissions) { await _permissionRepository.SetPermissions(participant, permissions); if (await _joinedParticipantsRepository.IsParticipantJoined(participant)) { appliedPermissions.Add(participant, permissions); } else { _logger.LogDebug("Participant {participantId} is not joined to the conference, remove permissions.", participant); await _permissionRepository.DeletePermissions(participant); } } if (appliedPermissions.Any()) { await _mediator.Publish(new ParticipantPermissionsUpdatedNotification(appliedPermissions)); } return(Unit.Value); }
public async Task <SuccessOrError <Unit> > Handle(SetTemporaryPermissionRequest request, CancellationToken cancellationToken) { var(participant, permissionKey, value) = request; if (!_permissionValidator.TryGetDescriptor(permissionKey, out var descriptor)) { return(PermissionsError.PermissionKeyNotFound(permissionKey)); } if (value != null) { if (!descriptor.ValidateValue(value)) { return(PermissionsError.InvalidPermissionValueType); } await _temporaryPermissionRepository.SetTemporaryPermission(participant, descriptor.Key, value); if (!await _participantsRepository.IsParticipantJoined(participant)) { _logger.LogDebug( "After setting temporary permissions for participant {participantId}, it was noticed that the participant is not currently joined. Remove temporary permission.", participant); await _temporaryPermissionRepository.RemoveAllTemporaryPermissions(participant); return(CommonError.ConcurrencyError); } } else { await _temporaryPermissionRepository.RemoveTemporaryPermission(participant, descriptor.Key); } await _mediator.Send(new UpdateParticipantsPermissionsRequest(participant.Yield())); await _mediator.Send(new UpdateSynchronizedObjectRequest(participant.ConferenceId, SynchronizedTemporaryPermissions.SyncObjId)); return(Unit.Value); }
public async Task <Unit> Handle(JoinConferenceRequest request, CancellationToken cancellationToken) { var(participant, connectionId, meta) = request; var(conferenceId, participantId) = participant; _logger.LogDebug("Participant {participantId} is joining conference {conferenceId}", participantId, conferenceId); var previousSession = await _joinedParticipantsRepository.AddParticipant(participant, connectionId); if (previousSession != null) { _logger.LogDebug("The participant {participantId} was already joined, kick existing connection.", participantId); await _mediator.Publish(new ParticipantKickedNotification( new Participant(previousSession.ConferenceId, participantId), previousSession.ConnectionId, ParticipantKickedReason.NewSessionConnected)); } await using var @lock = await _joinedParticipantsRepository.LockParticipantJoin(participant); if (!await _joinedParticipantsRepository.IsParticipantJoined(participant, connectionId)) { throw new ConcurrencyException("Race condition on participant join."); } _logger.LogDebug("Begin joining of participant {participant}", participant); // enable messaging just after kicking client await _mediator.Publish(new ParticipantInitializedNotification(participant)); // do not merge these together as handlers for ParticipantJoinedNotification may want to send messages to the participant await _mediator.Send(new EnableParticipantMessagingRequest(participant, connectionId), cancellationToken); await _mediator.Publish(new ParticipantJoinedNotification(participant, meta)); return(Unit.Value); }
public async Task <bool> Handle(CheckIsParticipantJoinedRequest request, CancellationToken cancellationToken) { return(await _repository.IsParticipantJoined(request.Participant)); }