diff --git a/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs b/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs new file mode 100644 index 0000000000..b5a8c14998 --- /dev/null +++ b/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +using HotChocolate; +using HotChocolate.Execution; +using HotChocolate.Subscriptions; +using HotChocolate.Types; + +using Tgstation.Server.Api.Rights; +using Tgstation.Server.Host.GraphQL.Types; +using Tgstation.Server.Host.Models.Transformers; +using Tgstation.Server.Host.Security; + +namespace Tgstation.Server.Host.GraphQL.Subscriptions +{ + /// + /// Subscriptions for . + /// + [ExtendObjectType(typeof(Subscription))] + public sealed class UserSubscriptions + { + /// + /// The name of the topic for when any user is updated. + /// + const string UserUpdatedTopic = "UserUpdated"; + + /// + /// Get the names of the topics to send to when a is updated. + /// + /// The of the updated . + /// An of topic s. + public static IEnumerable UserUpdatedTopics(long userId) + { + yield return UserUpdatedTopic; + yield return SpecificUserUpdatedTopic(userId); + } + + /// + /// The name of the topic for when a specific is updated. + /// + /// The of the updated . + /// The topic . + static string SpecificUserUpdatedTopic(long userId) + => $"{UserUpdatedTopic}.{userId}"; + + /// + /// Receive an update for all changes. + /// + /// The received from the publisher. + /// The updated . + [Subscribe] + [TgsGraphQLAuthorize(AdministrationRights.ReadUsers)] + public User UserUpdated([EventMessage] Models.User user) + { + ArgumentNullException.ThrowIfNull(user); + + return ((Models.IApiTransformable)user).ToApi(); + } + + /// + /// for . + /// + /// The . + /// The for the request. + /// The for the operation. + /// A resulting in a of the for the . + public ValueTask> CurrentUserUpdatedStream( + [Service] ITopicEventReceiver receiver, + [Service] IAuthenticationContext authenticationContext, + CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(receiver); + ArgumentNullException.ThrowIfNull(authenticationContext); + return receiver.SubscribeAsync(SpecificUserUpdatedTopic(Models.ModelExtensions.Require(authenticationContext.User, user => user.Id)), cancellationToken); + } + + /// + /// Receive an update to the logged in when it is changed. + /// + /// The received from the publisher. + /// The updated . + [Subscribe] + [TgsGraphQLAuthorize] + public User CurrentUserUpdated([EventMessage] Models.User user) + { + ArgumentNullException.ThrowIfNull(user); + + return ((Models.IApiTransformable)user).ToApi(); + } + } +}