예제 #1
0
        public override async Task <UpdateResp> Update(UpdateReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders);

            var updateSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new UserManagementMessage.Update(envelope, user, options.LoginName, options.FullName,
                                                            options.Groups.ToArray()));

            await updateSource.Task;

            return(new UpdateResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, updateSource))
                {
                    return;
                }

                updateSource.TrySetResult(true);
            }
        }
        public override async Task <StateResp> State(StateReq request, ServerCallContext context)
        {
            var resetSource = new TaskCompletionSource <Value>();

            var options = request.Options;

            var name      = options.Name;
            var partition = options.Partition ?? string.Empty;

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.GetState(envelope, name, partition));

            return(new StateResp {
                State = await resetSource.Task.ConfigureAwait(false)
            });

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.ProjectionState result))
                {
                    resetSource.TrySetException(UnknownMessage <ProjectionManagementMessage.ProjectionState>(message));
                    return;
                }

                var document = JsonDocument.Parse(result.State);

                resetSource.TrySetResult(GetProtoValue(document.RootElement));
            }
        }
예제 #3
0
        public override async Task <DisableResp> Disable(DisableReq request, ServerCallContext context)
        {
            var disableSource = new TaskCompletionSource <bool>();

            var options = request.Options;

            var user = context.GetHttpContext().User;

            var name  = options.Name;
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(options.WriteCheckpoint
                                ? (Message) new ProjectionManagementMessage.Command.Abort(envelope, name, runAs)
                                : new ProjectionManagementMessage.Command.Disable(envelope, name, runAs));

            await disableSource.Task.ConfigureAwait(false);

            return(new DisableResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    disableSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                disableSource.TrySetResult(true);
            }
        }
예제 #4
0
        public override async Task <ResetResp> Reset(ResetReq request, ServerCallContext context)
        {
            var resetSource = new TaskCompletionSource <bool>();

            var options = request.Options;

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, ResetOperation, context.CancellationToken)
                .ConfigureAwait(false))
            {
                throw AccessDenied();
            }
            var name  = options.Name;
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.Reset(envelope, name, runAs));

            await resetSource.Task.ConfigureAwait(false);

            return(new ResetResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    resetSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                resetSource.TrySetResult(true);
            }
        }
예제 #5
0
        public override async Task <DeleteResp> Delete(DeleteReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, DeleteOperation, context.CancellationToken).ConfigureAwait(false))
            {
                throw AccessDenied();
            }
            var deleteSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _publisher.Publish(new UserManagementMessage.Delete(envelope, user, options.LoginName));

            await deleteSource.Task.ConfigureAwait(false);

            return(new DeleteResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, deleteSource))
                {
                    return;
                }

                deleteSource.TrySetResult(true);
            }
        }
예제 #6
0
        public override async Task <EnableResp> Enable(EnableReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders).ConfigureAwait(false);

            var enableSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new UserManagementMessage.Enable(envelope, user, options.LoginName));

            await enableSource.Task.ConfigureAwait(false);

            return(new EnableResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, enableSource))
                {
                    return;
                }

                enableSource.TrySetResult(true);
            }
        }
예제 #7
0
        public override async Task <DisableResp> Disable(DisableReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;

            var disableSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new UserManagementMessage.Disable(envelope, user, options.LoginName));

            await disableSource.Task.ConfigureAwait(false);

            return(new DisableResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, disableSource))
                {
                    return;
                }

                disableSource.TrySetResult(true);
            }
        }
        public override async Task <DeleteResp> Delete(DeleteReq request, ServerCallContext context)
        {
            var deletedSource = new TaskCompletionSource <bool>();
            var options       = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders).ConfigureAwait(false);

            var name = options.Name;
            var deleteCheckpointStream = options.DeleteCheckpointStream;
            var deleteStateStream      = options.DeleteStateStream;
            var deleteEmittedStreams   = options.DeleteEmittedStreams;
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.Delete(envelope, name, runAs,
                                                                          deleteCheckpointStream, deleteStateStream, deleteEmittedStreams));

            await deletedSource.Task.ConfigureAwait(false);

            return(new DeleteResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    deletedSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                deletedSource.TrySetResult(true);
            }
        }
예제 #9
0
        public override async Task <CreateResp> Create(CreateReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;

            var createSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new UserManagementMessage.Create(envelope, user, options.LoginName, options.FullName,
                                                            options.Groups.ToArray(),
                                                            options.Password));

            await createSource.Task.ConfigureAwait(false);

            return(new CreateResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, createSource))
                {
                    return;
                }

                createSource.TrySetResult(true);
            }
        }
        public override async Task <ResetPasswordResp> ResetPassword(ResetPasswordReq request,
                                                                     ServerCallContext context)
        {
            var options = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders);

            var resetPasswordSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(
                new UserManagementMessage.ResetPassword(envelope, user, options.LoginName, options.NewPassword));

            await resetPasswordSource.Task;

            return(new ResetPasswordResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, resetPasswordSource))
                {
                    return;
                }

                resetPasswordSource.TrySetResult(true);
            }
        }
예제 #11
0
        public override async Task <ChangePasswordResp> ChangePassword(ChangePasswordReq request,
                                                                       ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;

            var changePasswordSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new UserManagementMessage.ChangePassword(envelope, user, options.LoginName,
                                                                    options.CurrentPassword,
                                                                    options.NewPassword));

            await changePasswordSource.Task.ConfigureAwait(false);

            return(new ChangePasswordResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, changePasswordSource))
                {
                    return;
                }

                changePasswordSource.TrySetResult(true);
            }
        }
예제 #12
0
        public override async Task <CreateResp> Create(CreateReq request, ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, CreateOperation, context.CancellationToken).ConfigureAwait(false))
            {
                throw RpcExceptions.AccessDenied();
            }
            var createSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _publisher.Publish(new UserManagementMessage.Create(envelope, user, options.LoginName, options.FullName,
                                                                options.Groups.ToArray(),
                                                                options.Password));

            await createSource.Task.ConfigureAwait(false);

            return(new CreateResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, createSource))
                {
                    return;
                }

                createSource.TrySetResult(true);
            }
        }
        private ClientMessage.WriteEvents UnwrapWriteEvents(TcpPackage package, IEnvelope envelope,
                                                            ClaimsPrincipal user, string login, string password)
        {
            var dto = package.Data.Deserialize <TcpClientMessageDto.WriteEvents>();

            if (dto == null)
            {
                return(null);
            }

            var events = new Event[dto.Events?.Length ?? 0];

            for (int i = 0; i < events.Length; ++i)
            {
                // ReSharper disable PossibleNullReferenceException
                var e = dto.Events[i];
                // ReSharper restore PossibleNullReferenceException
                events[i] = new Event(new Guid(e.EventId), e.EventType, e.DataContentType == 1, e.Data, e.Metadata);
            }

            var cts             = new CancellationTokenSource();
            var envelopeWrapper = new CallbackEnvelope(OnMessage);

            cts.CancelAfter(_writeTimeout);

            return(new ClientMessage.WriteEvents(Guid.NewGuid(), package.CorrelationId, envelopeWrapper, dto.RequireLeader,
                                                 dto.EventStreamId, dto.ExpectedVersion, events, user, login, password, cts.Token));

            void OnMessage(Message m)
            {
                cts.Dispose();
                envelope.ReplyWith(m);
            }
        }
        public override async Task <EnableResp> Enable(EnableReq request, ServerCallContext context)
        {
            var enableSource = new TaskCompletionSource <bool>();

            var options = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders);

            var name  = options.Name;
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.Enable(envelope, name, runAs));

            await enableSource.Task;

            return(new EnableResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    enableSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                enableSource.TrySetResult(true);
            }
        }
        public override async Task <CreateResp> Create(CreateReq request, ServerCallContext context)
        {
            var createdSource = new TaskCompletionSource <bool>();
            var options       = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders).ConfigureAwait(false);

            const string handlerType = "JS";
            var          name        = options.ModeCase switch {
                ModeOneofCase.Continuous => options.Continuous.Name,
                ModeOneofCase.Transient => options.Transient.Name,
                ModeOneofCase.OneTime => Guid.NewGuid().ToString("D"),
                _ => throw new InvalidOperationException()
            };
            var projectionMode = options.ModeCase switch {
                ModeOneofCase.Continuous => ProjectionMode.Continuous,
                ModeOneofCase.Transient => ProjectionMode.Transient,
                ModeOneofCase.OneTime => ProjectionMode.OneTime,
                _ => throw new InvalidOperationException()
            };
            var emitEnabled = options.ModeCase switch {
                ModeOneofCase.Continuous => options.Continuous.TrackEmittedStreams,
                _ => false
            };
            var checkpointsEnables = options.ModeCase switch {
                ModeOneofCase.Continuous => true,
                ModeOneofCase.OneTime => false,
                ModeOneofCase.Transient => false,
                _ => throw new InvalidOperationException()
            };
            var enabled             = true;
            var trackEmittedStreams = (options.ModeCase, emitEnabled) switch {
                (ModeOneofCase.Continuous, false) => true,
                _ => false
            };
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.Post(envelope, projectionMode, name, runAs,
                                                                        handlerType, options.Query, enabled, checkpointsEnables, emitEnabled, trackEmittedStreams, true));

            await createdSource.Task.ConfigureAwait(false);

            return(new CreateResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    createdSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                createdSource.TrySetResult(true);
            }
        }
    }
}
예제 #16
0
        public override async Task Details(DetailsReq request, IServerStreamWriter <DetailsResp> responseStream,
                                           ServerCallContext context)
        {
            var options = request.Options;

            var user = await GetUser(_authenticationProvider, context.RequestHeaders).ConfigureAwait(false);

            var detailsSource = new TaskCompletionSource <UserManagementMessage.UserData[]>();

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(string.IsNullOrWhiteSpace(options?.LoginName)
                                ? (Message) new UserManagementMessage.GetAll(envelope, user)
                                : new UserManagementMessage.Get(envelope, user, options.LoginName));

            var details = await detailsSource.Task.ConfigureAwait(false);

            foreach (var detail in details)
            {
                await responseStream.WriteAsync(new DetailsResp {
                    UserDetails = new DetailsResp.Types.UserDetails {
                        Disabled    = detail.Disabled,
                        Groups      = { detail.Groups },
                        FullName    = detail.FullName,
                        LoginName   = detail.LoginName,
                        LastUpdated = detail.DateLastUpdated.HasValue
                                                        ? new DetailsResp.Types.UserDetails.Types.DateTime
                        {
                            TicksSinceEpoch = detail.DateLastUpdated.Value.UtcDateTime.ToTicksSinceEpoch()
                        }
                                                        : null
                    }
                }).ConfigureAwait(false);
            }

            void OnMessage(Message message)
            {
                if (HandleErrors(options?.LoginName, message, detailsSource))
                {
                    return;
                }

                switch (message)
                {
                case UserManagementMessage.UserDetailsResult userDetails:
                    detailsSource.TrySetResult(new[] { userDetails.Data });
                    break;

                case UserManagementMessage.AllUserDetailsResult allUserDetails:
                    detailsSource.TrySetResult(allUserDetails.Data);
                    break;

                default:
                    detailsSource.TrySetException(RpcExceptions.UnknownError(1));
                    break;
                }
            }
        }
예제 #17
0
        public override async Task Statistics(StatisticsReq request, IServerStreamWriter <StatisticsResp> responseStream,
                                              ServerCallContext context)
        {
            var statsSource = new TaskCompletionSource <ProjectionStatistics[]>();

            var options = request.Options;
            var name    = string.IsNullOrEmpty(options.Name) ? null : options.Name;
            var mode    = options.ModeCase switch {
                ModeOneofCase.Continuous => ProjectionMode.Continuous,
                ModeOneofCase.Transient => ProjectionMode.Transient,
                ModeOneofCase.OneTime => ProjectionMode.OneTime,
                _ => default(Nullable <ProjectionMode>)
            };

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.GetStatistics(envelope, mode, name, true));

            foreach (var stats in Array.ConvertAll(await statsSource.Task.ConfigureAwait(false), s => new StatisticsResp.Types.Details {
                BufferedEvents = s.BufferedEvents,
                CheckpointStatus = s.CheckpointStatus,
                CoreProcessingTime = s.CoreProcessingTime,
                EffectiveName = s.EffectiveName,
                Epoch = s.Epoch,
                EventsProcessedAfterRestart = s.EventsProcessedAfterRestart,
                LastCheckpoint = s.LastCheckpoint,
                Mode = s.Mode.ToString(),
                Name = s.Name,
                ReadsInProgress = s.ReadsInProgress,
                PartitionsCached = s.PartitionsCached,
                Position = s.Position,
                Progress = s.Progress,
                StateReason = s.StateReason,
                Status = s.Status,
                Version = s.Version,
                WritePendingEventsAfterCheckpoint = s.WritePendingEventsAfterCheckpoint,
                WritePendingEventsBeforeCheckpoint = s.WritePendingEventsBeforeCheckpoint,
                WritesInProgress = s.WritesInProgress
            }))
            {
                await responseStream.WriteAsync(new StatisticsResp { Details = stats }).ConfigureAwait(false);
            }

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Statistics statistics))
                {
                    statsSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Statistics>(message));
                    return;
                }

                statsSource.TrySetResult(statistics.Projections);
            }
        }
    }
        public override async Task <StateResp> State(StateReq request, ServerCallContext context)
        {
            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, StateOperation, context.CancellationToken)
                .ConfigureAwait(false))
            {
                throw AccessDenied();
            }
            var resultSource = new TaskCompletionSource <Value>();

            var options = request.Options;

            var name      = options.Name;
            var partition = options.Partition ?? string.Empty;

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.GetState(envelope, name, partition));

            return(new StateResp {
                State = await resultSource.Task.ConfigureAwait(false)
            });

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.ProjectionState result))
                {
                    resultSource.TrySetException(UnknownMessage <ProjectionManagementMessage.ProjectionState>(message));
                    return;
                }

                if (string.IsNullOrEmpty(result.State))
                {
                    resultSource.TrySetResult(new Value {
                        StructValue = new Struct()
                    });
                    return;
                }
                var document = JsonDocument.Parse(result.State);

                resultSource.TrySetResult(GetProtoValue(document.RootElement));
            }
        }
예제 #19
0
        public override async Task <Empty> RestartPersistentSubscriptions(Empty request, ServerCallContext context)
        {
            var restart  = new TaskCompletionSource <bool>();
            var envelope = new CallbackEnvelope(OnMessage);

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, RestartPersistentSubscriptionsOperation,
                                                               context.CancellationToken)
                .ConfigureAwait(false))
            {
                throw RpcExceptions.AccessDenied();
            }

            _publisher.Publish(new SubscriptionMessage.PersistentSubscriptionsRestart(envelope));

            await restart.Task.ConfigureAwait(false);

            return(new Empty());

            void OnMessage(Message message)
            {
                switch (message)
                {
                case SubscriptionMessage.PersistentSubscriptionsRestarting _:
                    restart.TrySetResult(true);
                    break;

                case SubscriptionMessage.InvalidPersistentSubscriptionsRestart _:
                    restart.TrySetResult(true);
                    break;

                default:
                    restart.TrySetException(
                        RpcExceptions
                        .UnknownMessage <SubscriptionMessage.PersistentSubscriptionsRestarting>(message));
                    break;
                }
            }
        }
        public override async Task <ChangePasswordResp> ChangePassword(ChangePasswordReq request,
                                                                       ServerCallContext context)
        {
            var options = request.Options;

            var user = context.GetHttpContext().User;
            var changePasswordOperation = ChangePasswordOperation;

            if (user?.Identity?.Name != null)
            {
                changePasswordOperation =
                    changePasswordOperation.WithParameter(
                        Plugins.Authorization.Operations.Users.Parameters.User(user.Identity.Name));
            }
            if (!await _authorizationProvider.CheckAccessAsync(user, changePasswordOperation, context.CancellationToken).ConfigureAwait(false))
            {
                throw RpcExceptions.AccessDenied();
            }
            var changePasswordSource = new TaskCompletionSource <bool>();

            var envelope = new CallbackEnvelope(OnMessage);

            _publisher.Publish(new UserManagementMessage.ChangePassword(envelope, user, options.LoginName,
                                                                        options.CurrentPassword,
                                                                        options.NewPassword));

            await changePasswordSource.Task.ConfigureAwait(false);

            return(new ChangePasswordResp());

            void OnMessage(Message message)
            {
                if (HandleErrors(options.LoginName, message, changePasswordSource))
                {
                    return;
                }

                changePasswordSource.TrySetResult(true);
            }
        }
        public override async Task <Empty> RestartSubsystem(Empty empty, ServerCallContext context)
        {
            var restart  = new TaskCompletionSource <bool>();
            var envelope = new CallbackEnvelope(OnMessage);

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, RestartOperation, context.CancellationToken)
                .ConfigureAwait(false))
            {
                throw AccessDenied();
            }

            _queue.Publish(new ProjectionSubsystemMessage.RestartSubsystem(envelope));

            await restart.Task.ConfigureAwait(false);

            return(new Empty());

            void OnMessage(Message message)
            {
                switch (message)
                {
                case ProjectionSubsystemMessage.SubsystemRestarting _:
                    restart.TrySetResult(true);
                    break;

                case ProjectionSubsystemMessage.InvalidSubsystemRestart fail:
                    restart.TrySetException(InvalidSubsystemRestart(fail.SubsystemState));
                    break;

                default:
                    restart.TrySetException(
                        UnknownMessage <ProjectionSubsystemMessage.SubsystemRestarting>(message));
                    break;
                }
            }
        }
예제 #22
0
        public override async Task <DeleteResp> Delete(DeleteReq request, ServerCallContext context)
        {
            var deletedSource = new TaskCompletionSource <bool>();
            var options       = request.Options;

            var user = context.GetHttpContext().User;

            if (!await _authorizationProvider.CheckAccessAsync(user, DeleteOperation, context.CancellationToken)
                .ConfigureAwait(false))
            {
                throw RpcExceptions.AccessDenied();
            }
            var name = options.Name;
            var deleteCheckpointStream = options.DeleteCheckpointStream;
            var deleteStateStream      = options.DeleteStateStream;
            var deleteEmittedStreams   = options.DeleteEmittedStreams;
            var runAs = new ProjectionManagementMessage.RunAs(user);

            var envelope = new CallbackEnvelope(OnMessage);

            _queue.Publish(new ProjectionManagementMessage.Command.Delete(envelope, name, runAs,
                                                                          deleteCheckpointStream, deleteStateStream, deleteEmittedStreams));

            await deletedSource.Task.ConfigureAwait(false);

            return(new DeleteResp());

            void OnMessage(Message message)
            {
                if (!(message is ProjectionManagementMessage.Updated))
                {
                    deletedSource.TrySetException(UnknownMessage <ProjectionManagementMessage.Updated>(message));
                    return;
                }

                deletedSource.TrySetResult(true);
            }
        }
        private ClientMessage.DeleteStream UnwrapDeleteStream(TcpPackage package, IEnvelope envelope,
                                                              ClaimsPrincipal user, string login, string password)
        {
            var dto = package.Data.Deserialize <TcpClientMessageDto.DeleteStream>();

            if (dto == null)
            {
                return(null);
            }

            var cts             = new CancellationTokenSource();
            var envelopeWrapper = new CallbackEnvelope(OnMessage);

            cts.CancelAfter(_writeTimeout);

            return(new ClientMessage.DeleteStream(Guid.NewGuid(), package.CorrelationId, envelopeWrapper, dto.RequireLeader,
                                                  dto.EventStreamId, dto.ExpectedVersion, dto.HardDelete ?? false, user, login, password, cts.Token));

            void OnMessage(Message m)
            {
                cts.Dispose();
                envelope.ReplyWith(m);
            }
        }
예제 #24
0
        public override async Task <AppendResp> Append(
            IAsyncStreamReader <AppendReq> requestStream,
            ServerCallContext context)
        {
            if (!await requestStream.MoveNext().ConfigureAwait(false))
            {
                throw new InvalidOperationException();
            }

            if (requestStream.Current.ContentCase != AppendReq.ContentOneofCase.Options)
            {
                throw new InvalidOperationException();
            }

            var options    = requestStream.Current.Options;
            var streamName = options.StreamIdentifier;

            var expectedVersion = options.ExpectedStreamRevisionCase switch {
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Revision => new StreamRevision(
                    options.Revision).ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Any => AnyStreamRevision.Any.ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.StreamExists => AnyStreamRevision.StreamExists.ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.NoStream => AnyStreamRevision.NoStream.ToInt64(),
                _ => throw new InvalidOperationException()
            };

            var requiresLeader = GetRequiresLeader(context.RequestHeaders);

            var user = context.GetHttpContext().User;
            var op   = WriteOperation.WithParameter(Plugins.Authorization.Operations.Streams.Parameters.StreamId(streamName));

            if (!await _provider.CheckAccessAsync(user, op, context.CancellationToken).ConfigureAwait(false))
            {
                throw AccessDenied();
            }

            var correlationId = Guid.NewGuid();             // TODO: JPB use request id?

            var events = new List <Event>();

            var size = 0;

            while (await requestStream.MoveNext().ConfigureAwait(false))
            {
                if (requestStream.Current.ContentCase != AppendReq.ContentOneofCase.ProposedMessage)
                {
                    throw new InvalidOperationException();
                }

                var proposedMessage = requestStream.Current.ProposedMessage;
                var data            = proposedMessage.Data.ToByteArray();
                var metadata        = proposedMessage.CustomMetadata.ToByteArray();

                if (!proposedMessage.Metadata.TryGetValue(Constants.Metadata.Type, out var eventType))
                {
                    throw RpcExceptions.RequiredMetadataPropertyMissing(Constants.Metadata.Type);
                }

                if (!proposedMessage.Metadata.TryGetValue(Constants.Metadata.ContentType, out var contentType))
                {
                    throw RpcExceptions.RequiredMetadataPropertyMissing(Constants.Metadata.ContentType);
                }

                size += Event.SizeOnDisk(eventType, data, metadata);

                if (size > _maxAppendSize)
                {
                    throw RpcExceptions.MaxAppendSizeExceeded(_maxAppendSize);
                }

                events.Add(new Event(
                               Uuid.FromDto(proposedMessage.Id).ToGuid(),
                               eventType,
                               contentType == Constants.Metadata.ContentTypes.ApplicationJson,
                               data,
                               metadata));
            }

            var appendResponseSource = new TaskCompletionSource <AppendResp>();

            var envelope = new CallbackEnvelope(HandleWriteEventsCompleted);

            _publisher.Publish(new ClientMessage.WriteEvents(
                                   correlationId,
                                   correlationId,
                                   envelope,
                                   requiresLeader,
                                   streamName,
                                   expectedVersion,
                                   events.ToArray(),
                                   user,
                                   cancellationToken: context.CancellationToken));

            return(await appendResponseSource.Task.ConfigureAwait(false));

            void HandleWriteEventsCompleted(Message message)
            {
                if (message is ClientMessage.NotHandled notHandled && RpcExceptions.TryHandleNotHandled(notHandled, out var ex))
                {
                    appendResponseSource.TrySetException(ex);
                    return;
                }

                if (!(message is ClientMessage.WriteEventsCompleted completed))
                {
                    appendResponseSource.TrySetException(
                        RpcExceptions.UnknownMessage <ClientMessage.WriteEventsCompleted>(message));
                    return;
                }

                var response = new AppendResp();

                switch (completed.Result)
                {
                case OperationResult.Success:
                    response.Success = new AppendResp.Types.Success();
                    if (completed.LastEventNumber == -1)
                    {
                        response.Success.NoStream = new Empty();
                    }
                    else
                    {
                        response.Success.CurrentRevision = StreamRevision.FromInt64(completed.LastEventNumber);
                    }

                    if (completed.CommitPosition == -1)
                    {
                        response.Success.NoPosition = new Empty();
                    }
                    else
                    {
                        var position = Position.FromInt64(completed.CommitPosition, completed.PreparePosition);
                        response.Success.Position = new AppendResp.Types.Position {
                            CommitPosition  = position.CommitPosition,
                            PreparePosition = position.PreparePosition
                        };
                    }

                    appendResponseSource.TrySetResult(response);
                    return;

                case OperationResult.PrepareTimeout:
                case OperationResult.CommitTimeout:
                case OperationResult.ForwardTimeout:
                    appendResponseSource.TrySetException(RpcExceptions.Timeout());
                    return;

                case OperationResult.WrongExpectedVersion:
                    response.WrongExpectedVersion = new AppendResp.Types.WrongExpectedVersion();

                    switch (options.ExpectedStreamRevisionCase)
                    {
                    case AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Any:
                        response.WrongExpectedVersion.ExpectedAny = new Empty();
                        response.WrongExpectedVersion.Any2060     = new Empty();
                        break;

                    case AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.StreamExists:
                        response.WrongExpectedVersion.ExpectedStreamExists = new Empty();
                        response.WrongExpectedVersion.StreamExists2060     = new Empty();
                        break;

                    case AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.NoStream:
                        response.WrongExpectedVersion.ExpectedNoStream     = new Empty();
                        response.WrongExpectedVersion.ExpectedRevision2060 = ulong.MaxValue;
                        break;

                    case AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Revision:
                        response.WrongExpectedVersion.ExpectedRevision =
                            StreamRevision.FromInt64(expectedVersion);
                        response.WrongExpectedVersion.ExpectedRevision2060 =
                            StreamRevision.FromInt64(expectedVersion);
                        break;
                    }

                    if (completed.CurrentVersion == -1)
                    {
                        response.WrongExpectedVersion.CurrentNoStream = new Empty();
                        response.WrongExpectedVersion.NoStream2060    = new Empty();
                    }
                    else
                    {
                        response.WrongExpectedVersion.CurrentRevision =
                            StreamRevision.FromInt64(completed.CurrentVersion);
                        response.WrongExpectedVersion.CurrentRevision2060 =
                            StreamRevision.FromInt64(completed.CurrentVersion);
                    }

                    appendResponseSource.TrySetResult(response);
                    return;

                case OperationResult.StreamDeleted:
                    appendResponseSource.TrySetException(RpcExceptions.StreamDeleted(streamName));
                    return;

                case OperationResult.InvalidTransaction:
                    appendResponseSource.TrySetException(RpcExceptions.InvalidTransaction());
                    return;

                case OperationResult.AccessDenied:
                    appendResponseSource.TrySetException(RpcExceptions.AccessDenied());
                    return;

                default:
                    appendResponseSource.TrySetException(RpcExceptions.UnknownError(completed.Result));
                    return;
                }
            }
        }
    }
예제 #25
0
        public override async Task <AppendResp> Append(
            IAsyncStreamReader <AppendReq> requestStream,
            ServerCallContext context)
        {
            if (!await requestStream.MoveNext().ConfigureAwait(false))
            {
                throw new InvalidOperationException();
            }

            if (requestStream.Current.ContentCase != AppendReq.ContentOneofCase.Options)
            {
                throw new InvalidOperationException();
            }

            var options         = requestStream.Current.Options;
            var streamName      = options.StreamName;
            var expectedVersion = options.ExpectedStreamRevisionCase switch {
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Revision => new StreamRevision(
                    options.Revision).ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.Any => AnyStreamRevision.Any.ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.StreamExists => AnyStreamRevision.StreamExists.ToInt64(),
                AppendReq.Types.Options.ExpectedStreamRevisionOneofCase.NoStream => AnyStreamRevision.NoStream.ToInt64(),
                _ => throw new InvalidOperationException()
            };

            var user = await GetUser(_authenticationProvider, context.RequestHeaders).ConfigureAwait(false);

            var correlationId = Guid.NewGuid();             // TODO: JPB use request id?

            var events = new List <Event>();

            var size = 0;

            while (await requestStream.MoveNext().ConfigureAwait(false))
            {
                if (requestStream.Current.ContentCase != AppendReq.ContentOneofCase.ProposedMessage)
                {
                    throw new InvalidOperationException();
                }

                var proposedMessage = requestStream.Current.ProposedMessage;
                var data            = proposedMessage.Data.ToByteArray();
                size += data.Length;

                if (size > _maxAppendSize)
                {
                    throw RpcExceptions.MaxAppendSizeExceeded(_maxAppendSize);
                }

                if (!proposedMessage.Metadata.TryGetValue(Constants.Metadata.Type, out var eventType))
                {
                    throw RpcExceptions.RequiredMetadataPropertyMissing(Constants.Metadata.Type);
                }

                if (!proposedMessage.Metadata.TryGetValue(Constants.Metadata.IsJson, out var isJson))
                {
                    throw RpcExceptions.RequiredMetadataPropertyMissing(Constants.Metadata.IsJson);
                }

                events.Add(new Event(
                               Uuid.FromDto(proposedMessage.Id).ToGuid(),
                               eventType,
                               bool.Parse(isJson),
                               data,
                               proposedMessage.CustomMetadata.ToByteArray()));
            }

            var appendResponseSource = new TaskCompletionSource <AppendResp>();

            var envelope = new CallbackEnvelope(HandleWriteEventsCompleted);

            _queue.Publish(new ClientMessage.WriteEvents(
                               correlationId,
                               correlationId,
                               envelope,
                               true,
                               streamName,
                               expectedVersion,
                               events.ToArray(),
                               user));

            return(await appendResponseSource.Task.ConfigureAwait(false));

            void HandleWriteEventsCompleted(Message message)
            {
                if (message is ClientMessage.NotHandled notHandled && RpcExceptions.TryHandleNotHandled(notHandled, out var ex))
                {
                    appendResponseSource.TrySetException(ex);
                    return;
                }

                if (!(message is ClientMessage.WriteEventsCompleted completed))
                {
                    appendResponseSource.TrySetException(
                        RpcExceptions.UnknownMessage <ClientMessage.WriteEventsCompleted>(message));
                    return;
                }

                switch (completed.Result)
                {
                case OperationResult.Success:
                    var response = new AppendResp();

                    if (completed.LastEventNumber == -1)
                    {
                        response.NoStream = new AppendResp.Types.Empty();
                    }
                    else
                    {
                        response.CurrentRevision = StreamRevision.FromInt64(completed.LastEventNumber);
                    }

                    if (completed.CommitPosition == -1)
                    {
                        response.Empty = new AppendResp.Types.Empty();
                    }
                    else
                    {
                        var position = Position.FromInt64(completed.CommitPosition, completed.PreparePosition);
                        response.Position = new AppendResp.Types.Position {
                            CommitPosition  = position.CommitPosition,
                            PreparePosition = position.PreparePosition
                        };
                    }

                    appendResponseSource.TrySetResult(response);
                    return;

                case OperationResult.PrepareTimeout:
                case OperationResult.CommitTimeout:
                case OperationResult.ForwardTimeout:
                    appendResponseSource.TrySetException(RpcExceptions.Timeout());
                    return;

                case OperationResult.WrongExpectedVersion:
                    appendResponseSource.TrySetException(RpcExceptions.WrongExpectedVersion(
                                                             streamName,
                                                             expectedVersion,
                                                             completed.CurrentVersion));
                    return;

                case OperationResult.StreamDeleted:
                    appendResponseSource.TrySetException(RpcExceptions.StreamDeleted(streamName));
                    return;

                case OperationResult.InvalidTransaction:
                    appendResponseSource.TrySetException(RpcExceptions.InvalidTransaction());
                    return;

                case OperationResult.AccessDenied:
                    appendResponseSource.TrySetException(RpcExceptions.AccessDenied());
                    return;

                default:
                    appendResponseSource.TrySetException(RpcExceptions.UnknownError(completed.Result));
                    return;
                }
            }
        }
    }
예제 #26
0
        public override async Task Details(DetailsReq request, IServerStreamWriter <DetailsResp> responseStream,
                                           ServerCallContext context)
        {
            var options = request.Options;

            var user          = context.GetHttpContext().User;
            var readOperation = ReadOperation;

            if (user?.Identity?.Name != null)
            {
                readOperation =
                    readOperation.WithParameter(
                        Plugins.Authorization.Operations.Users.Parameters.User(user.Identity.Name));
            }
            if (!await _authorizationProvider.CheckAccessAsync(user, readOperation, context.CancellationToken).ConfigureAwait(false))
            {
                throw AccessDenied();
            }
            var detailsSource = new TaskCompletionSource <UserManagementMessage.UserData[]>();

            var envelope = new CallbackEnvelope(OnMessage);

            _publisher.Publish(string.IsNullOrWhiteSpace(options?.LoginName)
                                ? (Message) new UserManagementMessage.GetAll(envelope, user)
                                : new UserManagementMessage.Get(envelope, user, options.LoginName));

            var details = await detailsSource.Task.ConfigureAwait(false);

            foreach (var detail in details)
            {
                await responseStream.WriteAsync(new DetailsResp {
                    UserDetails = new DetailsResp.Types.UserDetails {
                        Disabled    = detail.Disabled,
                        Groups      = { detail.Groups },
                        FullName    = detail.FullName,
                        LoginName   = detail.LoginName,
                        LastUpdated = detail.DateLastUpdated.HasValue
                                                        ? new DetailsResp.Types.UserDetails.Types.DateTime
                        {
                            TicksSinceEpoch = detail.DateLastUpdated.Value.UtcDateTime.ToTicksSinceEpoch()
                        }
                                                        : null
                    }
                }).ConfigureAwait(false);
            }

            void OnMessage(Message message)
            {
                if (HandleErrors(options?.LoginName, message, detailsSource))
                {
                    return;
                }

                switch (message)
                {
                case UserManagementMessage.UserDetailsResult userDetails:
                    detailsSource.TrySetResult(new[] { userDetails.Data });
                    break;

                case UserManagementMessage.AllUserDetailsResult allUserDetails:
                    detailsSource.TrySetResult(allUserDetails.Data);
                    break;

                default:
                    detailsSource.TrySetException(RpcExceptions.UnknownError(1));
                    break;
                }
            }
        }
예제 #27
0
        protected override async Task Given()
        {
            var userCreated = new Dictionary <string, TaskCompletionSource <bool> > {
                [TestCredentials.TestUser1.Username] = new TaskCompletionSource <bool>(),
                [TestCredentials.TestUser2.Username] = new TaskCompletionSource <bool>(),
                [TestCredentials.TestAdmin.Username] = new TaskCompletionSource <bool>(),
            };

            var envelope = new CallbackEnvelope(OnUserCreated);

            Node.MainQueue.Publish(new UserManagementMessage.Create(envelope,
                                                                    SystemAccounts.System,
                                                                    TestCredentials.TestUser1.Username,
                                                                    nameof(TestCredentials.TestUser1),
                                                                    Array.Empty <string>(),
                                                                    TestCredentials.TestUser1.Password));
            Node.MainQueue.Publish(new UserManagementMessage.Create(envelope,
                                                                    SystemAccounts.System,
                                                                    TestCredentials.TestUser2.Username,
                                                                    nameof(TestCredentials.TestUser2),
                                                                    Array.Empty <string>(),
                                                                    TestCredentials.TestUser2.Password));
            Node.MainQueue.Publish(new UserManagementMessage.Create(envelope,
                                                                    SystemAccounts.System,
                                                                    TestCredentials.TestAdmin.Username,
                                                                    nameof(TestCredentials.TestAdmin),
                                                                    new[] { SystemRoles.Admins },
                                                                    TestCredentials.TestAdmin.Password));

            await Task.WhenAll(userCreated.Values.Select(x => x.Task)).WithTimeout(TimeSpan.FromSeconds(10));

            await Client.SetStreamMetadataAsync(NoAclStream, AnyStreamRevision.NoStream, new StreamMetadata());

            await Client.SetStreamMetadataAsync(
                ReadStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(TestCredentials.TestUser1.Username)));

            await Client.SetStreamMetadataAsync(
                WriteStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(writeRole : TestCredentials.TestUser1.Username)));

            await Client.SetStreamMetadataAsync(
                MetaReadStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(metaReadRole : TestCredentials.TestUser1.Username)));

            await Client.SetStreamMetadataAsync(
                MetaWriteStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(metaWriteRole : TestCredentials.TestUser1.Username)));

            await Client.SetStreamMetadataAsync(
                AllStream,
                AnyStreamRevision.Any,
                new StreamMetadata(acl : new StreamAcl(readRole : TestCredentials.TestUser1.Username)),
                userCredentials : TestCredentials.TestAdmin);

            await Client.SetStreamMetadataAsync(
                SystemAclStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(
                                       writeRole : TestCredentials.TestUser1.Username,
                                       readRole : TestCredentials.TestUser1.Username,
                                       metaWriteRole : TestCredentials.TestUser1.Username,
                                       metaReadRole : TestCredentials.TestUser1.Username)),
                userCredentials : TestCredentials.TestAdmin);

            await Client.SetStreamMetadataAsync(
                SystemAdminStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(
                                       writeRole : SystemRoles.Admins,
                                       readRole : SystemRoles.Admins,
                                       metaWriteRole : SystemRoles.Admins,
                                       metaReadRole : SystemRoles.Admins)),
                userCredentials : TestCredentials.TestAdmin);

            await Client.SetStreamMetadataAsync(
                NormalAllStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(
                                       writeRole : SystemRoles.All,
                                       readRole : SystemRoles.All,
                                       metaWriteRole : SystemRoles.All,
                                       metaReadRole : SystemRoles.All)));

            await Client.SetStreamMetadataAsync(
                SystemAllStream,
                AnyStreamRevision.NoStream,
                new StreamMetadata(acl : new StreamAcl(
                                       writeRole : SystemRoles.All,
                                       readRole : SystemRoles.All,
                                       metaWriteRole : SystemRoles.All,
                                       metaReadRole : SystemRoles.All)),
                userCredentials : TestCredentials.TestAdmin);


            void OnUserCreated(Message message)
            {
                Assert.True(message is UserManagementMessage.UpdateResult);

                userCreated[((UserManagementMessage.UpdateResult)message).LoginName].TrySetResult(true);
            }
        }
예제 #28
0
        private async Task <Position?> DeleteInternal(string streamName, long expectedVersion,
                                                      ClaimsPrincipal user, bool hardDelete, bool requiresLeader)
        {
            var correlationId        = Guid.NewGuid();      // TODO: JPB use request id?
            var deleteResponseSource = new TaskCompletionSource <Position?>();

            var envelope = new CallbackEnvelope(HandleStreamDeletedCompleted);

            _queue.Publish(new ClientMessage.DeleteStream(
                               correlationId,
                               correlationId,
                               envelope,
                               requiresLeader,
                               streamName,
                               expectedVersion,
                               hardDelete,
                               user));

            return(await deleteResponseSource.Task.ConfigureAwait(false));

            void HandleStreamDeletedCompleted(Message message)
            {
                if (message is ClientMessage.NotHandled notHandled &&
                    RpcExceptions.TryHandleNotHandled(notHandled, out var ex))
                {
                    deleteResponseSource.TrySetException(ex);
                    return;
                }

                if (!(message is ClientMessage.DeleteStreamCompleted completed))
                {
                    deleteResponseSource.TrySetException(
                        RpcExceptions.UnknownMessage <ClientMessage.DeleteStreamCompleted>(message));
                    return;
                }

                switch (completed.Result)
                {
                case OperationResult.Success:
                    deleteResponseSource.TrySetResult(completed.CommitPosition == -1
                                                        ? default
                                                        : Position.FromInt64(completed.CommitPosition, completed.PreparePosition));

                    return;

                case OperationResult.PrepareTimeout:
                case OperationResult.CommitTimeout:
                case OperationResult.ForwardTimeout:
                    deleteResponseSource.TrySetException(RpcExceptions.Timeout());
                    return;

                case OperationResult.WrongExpectedVersion:
                    deleteResponseSource.TrySetException(RpcExceptions.WrongExpectedVersion(streamName,
                                                                                            expectedVersion));
                    return;

                case OperationResult.StreamDeleted:
                    deleteResponseSource.TrySetException(RpcExceptions.StreamDeleted(streamName));
                    return;

                case OperationResult.InvalidTransaction:
                    deleteResponseSource.TrySetException(RpcExceptions.InvalidTransaction());
                    return;

                case OperationResult.AccessDenied:
                    deleteResponseSource.TrySetException(RpcExceptions.AccessDenied());
                    return;

                default:
                    deleteResponseSource.TrySetException(RpcExceptions.UnknownError(completed.Result));
                    return;
                }
            }
        }