Example #1
0
 public static async Task SetAsync <T>(this IDistributedCache cache, string key, T value, DistributedCacheEntryOptions options, DefaultJsonSerializer jsonSerializer, CancellationToken ct)
 {
     var valueData = jsonSerializer.SerializeToUtf8Bytes(value);
     await cache.SetAsync(key, valueData, options, ct);
 }
        public IActionResult SSOAuthorizeAsync([FromQuery, BindRequired] Guid uuid, [FromServices] NexusModsAPIKeyProvider apiKeyProvider, [FromServices] DefaultJsonSerializer jsonSerializer, CancellationToken ct)
        {
            async IAsyncEnumerable <SSEMessage> SSEEvents()
            {
                var client = new ClientWebSocket();

                using var cts       = new CancellationTokenSource(60000);
                using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, ct);
                var timeoutToken    = linkedCts.Token;
                var connectionToken = null as string;

                yield return(new SSEMessage(Event: "connecting"));

                var receivedAPIKey = false;

                async Task ReceiveLoop()
                {
                    var buffer = new ArraySegment <byte>(new byte[1024]);
                    var sb     = new StringBuilder();

                    while (!timeoutToken.IsCancellationRequested && client.State == WebSocketState.Open)
                    {
                        var received = await client.ReceiveAsync(buffer, timeoutToken);

                        if (received.MessageType == WebSocketMessageType.Close)
                        {
                            break;
                        }

                        sb.Append(Encoding.UTF8.GetString(buffer.AsSpan(0, received.Count)));
                        if (received.EndOfMessage)
                        {
                            var text = sb.ToString();
                            sb.Clear();

                            var response = jsonSerializer.Deserialize <SSOResponse?>(text);
                            if (response is not null && response.Success && response.Data is not null)
                            {
                                if (response.Data.ConnectionToken is not null)
                                {
                                    connectionToken = response.Data.ConnectionToken;
                                }

                                if (response.Data.ApiKey is not null)
                                {
                                    receivedAPIKey = true;
                                    apiKeyProvider.Override(response.Data.ApiKey);
                                    await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye", timeoutToken);
                                }
                            }
                        }
                    }
                }

                await client.ConnectAsync(new Uri("wss://sso.nexusmods.com"), timeoutToken);

                var receiveTask = ReceiveLoop();
                var request     = jsonSerializer.SerializeToUtf8Bytes(new SSORequest(uuid, connectionToken, 2));
                await client.SendAsync(request, WebSocketMessageType.Text, true, timeoutToken);

                yield return(new SSEMessage(Event: "connected"));

                await receiveTask;

                if (!receivedAPIKey)
                {
                    yield return(new SSEMessage(Event: "api-key-failed-to-get"));
                }
                else
                {
                    yield return(new SSEMessage(Event: "api-key-received"));
                }

                yield return(new SSEMessage(Event: "finished"));
            }

            return(new SSEActionResult(SSEEvents()));
        }