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)); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } } } }
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; } } }
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)); } }
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; } } }
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); } }
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; } } } }
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; } } } }
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; } } }
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); } }
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; } } }