Esempio n. 1
0
        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));
 }