diff --git a/src/Nullinside.Api.Common.AspNetCore/Middleware/BasicAuthenticationHandler.cs b/src/Nullinside.Api.Common.AspNetCore/Middleware/BasicAuthenticationHandler.cs index 3699959..dc91dc5 100644 --- a/src/Nullinside.Api.Common.AspNetCore/Middleware/BasicAuthenticationHandler.cs +++ b/src/Nullinside.Api.Common.AspNetCore/Middleware/BasicAuthenticationHandler.cs @@ -61,7 +61,7 @@ protected override async Task HandleAuthenticateAsync() { .AsNoTracking() .FirstOrDefaultAsync(u => !string.IsNullOrWhiteSpace(u.Token) && u.Token == token && - !u.IsBanned); + !u.IsBanned).ConfigureAwait(false); if (null == dbUser) { return AuthenticateResult.Fail("Invalid token"); diff --git a/src/Nullinside.Api.Common.AspNetCore/Nullinside.Api.Common.AspNetCore.csproj.DotSettings b/src/Nullinside.Api.Common.AspNetCore/Nullinside.Api.Common.AspNetCore.csproj.DotSettings index 89316e4..4527ed0 100644 --- a/src/Nullinside.Api.Common.AspNetCore/Nullinside.Api.Common.AspNetCore.csproj.DotSettings +++ b/src/Nullinside.Api.Common.AspNetCore/Nullinside.Api.Common.AspNetCore.csproj.DotSettings @@ -1,2 +1,4 @@ - + Library \ No newline at end of file diff --git a/src/Nullinside.Api.Common/Docker/DockerProxy.cs b/src/Nullinside.Api.Common/Docker/DockerProxy.cs index 2113312..a559558 100644 --- a/src/Nullinside.Api.Common/Docker/DockerProxy.cs +++ b/src/Nullinside.Api.Common/Docker/DockerProxy.cs @@ -40,7 +40,7 @@ public class DockerProxy : IDockerProxy { /// public async Task> GetContainers(CancellationToken cancellationToken) { (string output, string error) response = - await ExecuteCommand("docker container ls -a --format '{{.Names}}|{{.Status}}'", cancellationToken); + await ExecuteCommand("docker container ls -a --format '{{.Names}}|{{.Status}}'", cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(response.output)) { return Enumerable.Empty(); } @@ -69,7 +69,7 @@ public async Task> GetContainers(CancellationToken c /// public async Task> GetDockerComposeProjects(CancellationToken cancellationToken) { (string output, string error) responseJson = - await ExecuteCommand("docker compose ls -a --format 'json'", cancellationToken); + await ExecuteCommand("docker compose ls -a --format 'json'", cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(responseJson.output)) { return Enumerable.Empty(); } @@ -89,7 +89,7 @@ public async Task> GetDockerComposeProjects(Cancella public async Task TurnOnOffDockerContainer(string name, bool turnOn, CancellationToken cancellationToken) { string command = turnOn ? "start" : "stop"; (string output, string error) responseJson = - await ExecuteCommand($"docker container {command} {name}", cancellationToken); + await ExecuteCommand($"docker container {command} {name}", cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(responseJson.error)) { return false; } @@ -101,11 +101,11 @@ public async Task TurnOnOffDockerContainer(string name, bool turnOn, Cance /// public async Task TurnOnOffDockerCompose(string name, bool turnOn, CancellationToken cancellationToken, string? backupFolder) { - IEnumerable existing = await GetDockerComposeProjects(cancellationToken); + IEnumerable existing = await GetDockerComposeProjects(cancellationToken).ConfigureAwait(false); if (null != existing.FirstOrDefault(e => name.Equals(e.Name))) { string command = turnOn ? "start" : "stop"; (string output, string error) stdout = - await ExecuteCommand($"docker compose -p {name} {command}", cancellationToken); + await ExecuteCommand($"docker compose -p {name} {command}", cancellationToken).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(stdout.error)) { return false; } @@ -119,7 +119,7 @@ public async Task TurnOnOffDockerCompose(string name, bool turnOn, Cancell } (string output, string error) - output = await ExecuteCommand("docker compose up -d", cancellationToken, backupFolder); + output = await ExecuteCommand("docker compose up -d", cancellationToken, backupFolder).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(output.error)) { return false; } @@ -138,7 +138,7 @@ public async Task TurnOnOffDockerCompose(string name, bool turnOn, Cancell private async Task<(string output, string error)> ExecuteCommand(string command, CancellationToken token = new(), string? dir = null) { using SshClient client = new(_server!, _username!, _password!); - await client.ConnectAsync(token); + await client.ConnectAsync(token).ConfigureAwait(false); using SshCommand? responseJson = client.RunCommand($"cd {dir}; echo {_password2} | sudo -S {command}"); return (responseJson.Result, responseJson.Error); } diff --git a/src/Nullinside.Api.Common/Extensions/WebSocketExtensions.cs b/src/Nullinside.Api.Common/Extensions/WebSocketExtensions.cs index 6811d86..8eb5435 100644 --- a/src/Nullinside.Api.Common/Extensions/WebSocketExtensions.cs +++ b/src/Nullinside.Api.Common/Extensions/WebSocketExtensions.cs @@ -14,7 +14,7 @@ public static class WebSocketExtensions { /// The message to send. /// The cancellation token. public static async Task SendTextAsync(this WebSocket webSocket, string message, CancellationToken cancelToken = new()) { - await webSocket.SendAsync(Encoding.ASCII.GetBytes(message), WebSocketMessageType.Text, true, cancelToken); + await webSocket.SendAsync(Encoding.ASCII.GetBytes(message), WebSocketMessageType.Text, true, cancelToken).ConfigureAwait(false); } /// @@ -29,7 +29,7 @@ public static class WebSocketExtensions { do { var data = new ArraySegment(new byte[1024]); - response = await webSocket.ReceiveAsync(data, cancelToken); + response = await webSocket.ReceiveAsync(data, cancelToken).ConfigureAwait(false); fullMessage.AddRange(data); } while (null == response.CloseStatus && !response.EndOfMessage); diff --git a/src/Nullinside.Api.Common/Nullinside.Api.Common.csproj.DotSettings b/src/Nullinside.Api.Common/Nullinside.Api.Common.csproj.DotSettings index 89316e4..4527ed0 100644 --- a/src/Nullinside.Api.Common/Nullinside.Api.Common.csproj.DotSettings +++ b/src/Nullinside.Api.Common/Nullinside.Api.Common.csproj.DotSettings @@ -1,2 +1,4 @@ - + Library \ No newline at end of file diff --git a/src/Nullinside.Api.Common/Retry.cs b/src/Nullinside.Api.Common/Retry.cs index 15f5bc9..f3a34f8 100644 --- a/src/Nullinside.Api.Common/Retry.cs +++ b/src/Nullinside.Api.Common/Retry.cs @@ -32,7 +32,7 @@ public static class Retry { Exception? exceptionToThrow = null; while (tries <= numberOfRetries && !token.IsCancellationRequested) { try { - return await action(); + return await action().ConfigureAwait(false); } catch (Exception ex) { exceptionToThrow = ex; @@ -40,7 +40,7 @@ public static class Retry { // Why did I do as delay THEN method? Honestly...I don't have a good reason. You can change it if you want, just // update the documentation if you do. - await Task.Delay(waitTime.HasValue ? (int)waitTime.Value.TotalMilliseconds : 1000, token); + await Task.Delay(waitTime.HasValue ? (int)waitTime.Value.TotalMilliseconds : 1000, token).ConfigureAwait(false); if (null != runOnFailure) { runOnFailure(ex); } diff --git a/src/Nullinside.Api.Common/Twitch/TwitchApiProxy.cs b/src/Nullinside.Api.Common/Twitch/TwitchApiProxy.cs index 7b8dc83..40c1a58 100644 --- a/src/Nullinside.Api.Common/Twitch/TwitchApiProxy.cs +++ b/src/Nullinside.Api.Common/Twitch/TwitchApiProxy.cs @@ -88,7 +88,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, public virtual async Task CreateAccessToken(string code, CancellationToken token = new()) { ITwitchAPI api = GetApi(); AuthCodeResponse? response = await api.Auth.GetAccessTokenFromCodeAsync(code, TwitchAppConfig?.ClientSecret, - TwitchAppConfig?.ClientRedirect); + TwitchAppConfig?.ClientRedirect).ConfigureAwait(false); if (null == response) { return null; } @@ -109,7 +109,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, } ITwitchAPI api = GetApi(); - RefreshResponse? response = await api.Auth.RefreshAuthTokenAsync(OAuth?.RefreshToken, TwitchAppConfig?.ClientSecret, TwitchAppConfig?.ClientId); + RefreshResponse? response = await api.Auth.RefreshAuthTokenAsync(OAuth?.RefreshToken, TwitchAppConfig?.ClientSecret, TwitchAppConfig?.ClientId).ConfigureAwait(false); if (null == response) { return null; } @@ -129,7 +129,7 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, /// public async Task GetAccessTokenIsValid(CancellationToken token = new()) { try { - return !string.IsNullOrWhiteSpace((await GetUser(token))?.Id); + return !string.IsNullOrWhiteSpace((await GetUser(token).ConfigureAwait(false))?.Id); } catch { return false; @@ -140,40 +140,40 @@ public TwitchApiProxy(string token, string refreshToken, DateTime tokenExpires, public virtual async Task GetUser(CancellationToken token = new()) { return await Retry.Execute(async () => { ITwitchAPI api = GetApi(); - GetUsersResponse? response = await api.Helix.Users.GetUsersAsync(); + GetUsersResponse? response = await api.Helix.Users.GetUsersAsync().ConfigureAwait(false); if (null == response) { return null; } return response.Users.FirstOrDefault(); - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// public virtual async Task<(string? id, string? username)> GetUser(string username, CancellationToken token = new()) { return await Retry.Execute(async () => { ITwitchAPI api = GetApi(); - GetUsersResponse? response = await api.Helix.Users.GetUsersAsync(logins: [username]); + GetUsersResponse? response = await api.Helix.Users.GetUsersAsync(logins: [username]).ConfigureAwait(false); if (null == response) { return (null, null); } User? user = response.Users.FirstOrDefault(); return (user?.Id, user?.Login); - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// public virtual async Task GetUserEmail(CancellationToken token = new()) { return await Retry.Execute(async () => { ITwitchAPI api = GetApi(); - GetUsersResponse? response = await api.Helix.Users.GetUsersAsync(); + GetUsersResponse? response = await api.Helix.Users.GetUsersAsync().ConfigureAwait(false); if (null == response) { return null; } return response.Users.FirstOrDefault()?.Email; - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// @@ -192,9 +192,9 @@ public virtual async Task> GetUserModChannel request.Headers.Add("Authorization", $"Bearer {OAuth?.AccessToken}"); request.Headers.Add("Client-Id", TwitchAppConfig?.ClientId); - using HttpResponseMessage response = await client.SendAsync(request); + using HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - string responseBody = await response.Content.ReadAsStringAsync(); + string responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var moderatedChannels = JsonConvert.DeserializeObject(responseBody); if (null == moderatedChannels) { break; @@ -219,7 +219,7 @@ public virtual async Task> BanChannelUsers(string channe BanUserResponse? response = await api.Helix.Moderation.BanUserAsync(channelId, botId, new BanUserRequest { UserId = user.Id, Reason = reason - }); + }).ConfigureAwait(false); if (null == response || null == response.Data) { continue; @@ -229,7 +229,7 @@ public virtual async Task> BanChannelUsers(string channe LOG.Info($"Banned {user.Username} ({user.Id}) in {channelId}: {reason}"); } catch (HttpResponseException ex) { - string exceptionReason = await ex.HttpResponse.Content.ReadAsStringAsync(token); + string exceptionReason = await ex.HttpResponse.Content.ReadAsStringAsync(token).ConfigureAwait(false); LOG.Debug($"Failed to ban {user.Username} ({user.Id}) in {channelId}: {exceptionReason}", ex); } catch (Exception ex) { @@ -238,7 +238,7 @@ public virtual async Task> BanChannelUsers(string channe } return bannedUsers; - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// @@ -250,7 +250,7 @@ public virtual async Task> GetChannelUsers(string channelId string? cursor = null; int total = 0; do { - GetChattersResponse? response = await api.Helix.Chat.GetChattersAsync(channelId, botId, 1000, cursor); + GetChattersResponse? response = await api.Helix.Chat.GetChattersAsync(channelId, botId, 1000, cursor).ConfigureAwait(false); if (null == response) { break; } @@ -262,7 +262,7 @@ public virtual async Task> GetChannelUsers(string channelId Debug.Assert(chatters.Count == total); return chatters; - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// @@ -279,7 +279,7 @@ public virtual async Task> GetChannelsLive(IEnumerable "live".Equals(s.Type, StringComparison.InvariantCultureIgnoreCase))); @@ -298,7 +298,7 @@ public virtual async Task> GetChannelsLive(IEnumerable> GetChannelsLive(IEnumerable public virtual async Task AddChannelMod(string channelId, string userId, CancellationToken token = new()) { return await Retry.Execute(async () => { ITwitchAPI api = GetApi(); - await api.Helix.Moderation.AddChannelModeratorAsync(channelId, userId); + await api.Helix.Moderation.AddChannelModeratorAsync(channelId, userId).ConfigureAwait(false); return true; - }, Retries, token); + }, Retries, token).ConfigureAwait(false); } /// diff --git a/src/Nullinside.Api.Common/Twitch/TwitchClientProxy.cs b/src/Nullinside.Api.Common/Twitch/TwitchClientProxy.cs index bfbea60..35dd5ff 100644 --- a/src/Nullinside.Api.Common/Twitch/TwitchClientProxy.cs +++ b/src/Nullinside.Api.Common/Twitch/TwitchClientProxy.cs @@ -150,7 +150,7 @@ public async Task SendMessage(string channel, string message, uint retryCo // Try to connect and join the channel. bool connectedAndJoined = false; for (int i = 0; i < retryConnection; i++) { - if (await JoinChannel(channel)) { + if (await JoinChannel(channel).ConfigureAwait(false)) { connectedAndJoined = true; break; } @@ -184,7 +184,7 @@ public async Task SendMessage(string channel, string message, uint retryCo /// public async Task AddMessageCallback(string channel, Action callback) { - await JoinChannel(channel); + await JoinChannel(channel).ConfigureAwait(false); string channelSan = channel.ToLowerInvariant(); lock (_onMessageReceived) { if (!_onMessageReceived.TryAdd(channelSan, callback)) { @@ -223,7 +223,7 @@ public void RemoveMessageCallback(string channel, Action /// public async Task AddBannedCallback(string channel, Action callback) { - await JoinChannel(channel); + await JoinChannel(channel).ConfigureAwait(false); lock (_onUserBanReceived) { _onUserBanReceived[channel] = callback; @@ -250,7 +250,7 @@ public void RemoveDisconnectedCallback(Action callback) { /// public async Task AddRaidCallback(string channel, Action callback) { - await JoinChannel(channel); + await JoinChannel(channel).ConfigureAwait(false); lock (_onRaid) { _onRaid[channel] = callback; @@ -282,7 +282,7 @@ private async Task JoinChannel(string channel) { } // Try to connect. - if (!await Connect()) { + if (!await Connect().ConfigureAwait(false)) { return false; } @@ -319,7 +319,7 @@ private async Task JoinChannel(string channel) { /// The event arguments. private async void TwitchChatClientReconnectOnElapsed(object? sender, ElapsedEventArgs e) { // Connect the chat client. - await Connect(); + await Connect().ConfigureAwait(false); // Pull the master list of channels we should be connected to the stack. string[]? allChannels = null; @@ -329,7 +329,7 @@ private async void TwitchChatClientReconnectOnElapsed(object? sender, ElapsedEve // Join all the channels. foreach (string channel in allChannels) { - await JoinChannel(channel); + await JoinChannel(channel).ConfigureAwait(false); } // Restart the timer. diff --git a/src/Nullinside.Api.Model/Nullinside.Api.Model.csproj.DotSettings b/src/Nullinside.Api.Model/Nullinside.Api.Model.csproj.DotSettings index 89316e4..4527ed0 100644 --- a/src/Nullinside.Api.Model/Nullinside.Api.Model.csproj.DotSettings +++ b/src/Nullinside.Api.Model/Nullinside.Api.Model.csproj.DotSettings @@ -1,2 +1,4 @@ - + Library \ No newline at end of file diff --git a/src/Nullinside.Api.Model/Shared/DatabaseLock.cs b/src/Nullinside.Api.Model/Shared/DatabaseLock.cs index 9574712..183dc05 100644 --- a/src/Nullinside.Api.Model/Shared/DatabaseLock.cs +++ b/src/Nullinside.Api.Model/Shared/DatabaseLock.cs @@ -48,7 +48,7 @@ public void Dispose() { // This is only used with hard coded names. #pragma warning disable EF1002 - await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT GET_LOCK('{name}', -1)", cancellationToken); + await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT GET_LOCK('{name}', -1)", cancellationToken).ConfigureAwait(false); #pragma warning restore EF1002 _name = name; return true; @@ -63,13 +63,13 @@ public void Dispose() { if (!string.IsNullOrWhiteSpace(name) && !name.Equals(_name, StringComparison.InvariantCultureIgnoreCase)) { // This is only used with hard coded names. #pragma warning disable EF1002 - await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT RELEASE_LOCK('{_name}')", cancellationToken); + await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT RELEASE_LOCK('{_name}')", cancellationToken).ConfigureAwait(false); #pragma warning restore EF1002 } // This is only used with hard coded names. #pragma warning disable EF1002 - await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT RELEASE_LOCK('{name}')", cancellationToken); + await _mysqlDbContext.Database.ExecuteSqlRawAsync($"SELECT RELEASE_LOCK('{name}')", cancellationToken).ConfigureAwait(false); #pragma warning restore EF1002 _name = null; } diff --git a/src/Nullinside.Api.Model/Shared/UserHelpers.cs b/src/Nullinside.Api.Model/Shared/UserHelpers.cs index 7e62d89..dcd24cc 100644 --- a/src/Nullinside.Api.Model/Shared/UserHelpers.cs +++ b/src/Nullinside.Api.Model/Shared/UserHelpers.cs @@ -27,9 +27,9 @@ public static class UserHelpers { string? twitchUsername = null, string? twitchId = null) { string bearerToken = AuthUtils.GenerateBearerToken(); try { - User? existing = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email && !u.IsBanned, token); + User? existing = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email && !u.IsBanned, token).ConfigureAwait(false); if (null == existing && !string.IsNullOrWhiteSpace(twitchUsername)) { - existing = await dbContext.Users.FirstOrDefaultAsync(u => u.TwitchUsername == twitchUsername && !u.IsBanned, token); + existing = await dbContext.Users.FirstOrDefaultAsync(u => u.TwitchUsername == twitchUsername && !u.IsBanned, token).ConfigureAwait(false); } if (null == existing) { @@ -45,9 +45,9 @@ public static class UserHelpers { CreatedOn = DateTime.UtcNow }); - await dbContext.SaveChangesAsync(token); + await dbContext.SaveChangesAsync(token).ConfigureAwait(false); - existing = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email, token); + existing = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email, token).ConfigureAwait(false); if (null == existing) { return null; } @@ -68,7 +68,7 @@ public static class UserHelpers { existing.UpdatedOn = DateTime.UtcNow; } - await dbContext.SaveChangesAsync(token); + await dbContext.SaveChangesAsync(token).ConfigureAwait(false); return bearerToken; } catch { diff --git a/src/Nullinside.Api.Tests/Nullinside.Api.Model/Shared/UserHelpersTests.cs b/src/Nullinside.Api.Tests/Nullinside.Api.Model/Shared/UserHelpersTests.cs index b464526..8f09485 100644 --- a/src/Nullinside.Api.Tests/Nullinside.Api.Model/Shared/UserHelpersTests.cs +++ b/src/Nullinside.Api.Tests/Nullinside.Api.Model/Shared/UserHelpersTests.cs @@ -17,13 +17,13 @@ public async Task GenerateTokenForExistingUser() { Email = "email" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Verify there is only one user Assert.That(_db.Users.Count(), Is.EqualTo(1)); // Generate a new token - string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(_db, "email"); + string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(_db, "email").ConfigureAwait(false); Assert.That(token, Is.Not.Null); // Verify we still only have one user @@ -42,13 +42,13 @@ public async Task GenerateTokenForNewUser() { Email = "email2" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Verify there is only one user Assert.That(_db.Users.Count(), Is.EqualTo(1)); // Generate a new token - string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(_db, "email"); + string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(_db, "email").ConfigureAwait(false); Assert.That(token, Is.Not.Null); // Verify we have a new user @@ -65,7 +65,7 @@ public async Task GenerateTokenForNewUser() { [Test] public async Task HandleUnexpectedErrors() { // Force an error to occur. - string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(null!, "email"); + string? token = await UserHelpers.GenerateTokenAndSaveToDatabase(null!, "email").ConfigureAwait(false); Assert.That(token, Is.Null); } } \ No newline at end of file diff --git a/src/Nullinside.Api.Tests/Nullinside.Api.Tests.csproj.DotSettings b/src/Nullinside.Api.Tests/Nullinside.Api.Tests.csproj.DotSettings index 89316e4..4527ed0 100644 --- a/src/Nullinside.Api.Tests/Nullinside.Api.Tests.csproj.DotSettings +++ b/src/Nullinside.Api.Tests/Nullinside.Api.Tests.csproj.DotSettings @@ -1,2 +1,4 @@ - + Library \ No newline at end of file diff --git a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/DockerControllerTests.cs b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/DockerControllerTests.cs index aa475da..8e86452 100644 --- a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/DockerControllerTests.cs +++ b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/DockerControllerTests.cs @@ -47,7 +47,7 @@ public async Task DatabaseMatchesCommandOutputSuccessfully() { Notes = "Should be in output" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Create two entries "in the server" for what is actually running. We should only match on the "good" one. The bad // one is different enough that it shouldn't match. @@ -66,7 +66,7 @@ public async Task DatabaseMatchesCommandOutputSuccessfully() { // Make the call and ensure it's successful. var controller = new DockerController(_db, _docker.Object); - ObjectResult obj = await controller.GetDockerResources(); + ObjectResult obj = await controller.GetDockerResources().ConfigureAwait(false); Assert.That(obj.StatusCode, Is.EqualTo(200)); // There should be three results. One that was actively running "Good" and the others weren't actively running. @@ -92,7 +92,7 @@ public async Task OnOffComposeProjectsWork() { Id = 2, DisplayName = "Bad", IsDockerComposeProject = true, Name = "Bad", Notes = "Should not be in output" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Only a call with "Good" will work. _docker.Setup(d => @@ -102,7 +102,7 @@ public async Task OnOffComposeProjectsWork() { // Make the call and ensure it's successful. var controller = new DockerController(_db, _docker.Object); ObjectResult obj = - await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }); + await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }).ConfigureAwait(false); Assert.That(obj.StatusCode, Is.EqualTo(200)); // Ensure we called the 3rd party API with a value of "Good" to turn on a compose. @@ -124,7 +124,7 @@ public async Task OnOffContainerWork() { Id = 2, DisplayName = "Bad", IsDockerComposeProject = false, Name = "Bad", Notes = "Should not be in output" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Only a call with "Good" will work. _docker.Setup(d => d.TurnOnOffDockerContainer("Good", It.IsAny(), It.IsAny())) @@ -133,7 +133,7 @@ public async Task OnOffContainerWork() { // Make the call and ensure it's successful. var controller = new DockerController(_db, _docker.Object); ObjectResult obj = - await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }); + await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }).ConfigureAwait(false); Assert.That(obj.StatusCode, Is.EqualTo(200)); // Ensure we called the 3rd party API with a value of "Good" to turn on a container. @@ -152,7 +152,7 @@ public async Task InvalidIdIsBadRequest() { Id = 2, DisplayName = "Bad", IsDockerComposeProject = false, Name = "Bad", Notes = "Should not be in output" } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Only a call with "Good" will get true. _docker.Setup(d => d.TurnOnOffDockerContainer("Good", It.IsAny(), It.IsAny())) @@ -161,7 +161,7 @@ public async Task InvalidIdIsBadRequest() { // Make the call and ensure it's successful. var controller = new DockerController(_db, _docker.Object); ObjectResult obj = - await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }); + await controller.TurnOnOrOffDockerResources(1, new TurnOnOrOffDockerResourcesRequest { TurnOn = true }).ConfigureAwait(false); Assert.That(obj.StatusCode, Is.EqualTo(400)); // Bad request is returned to user with a generic error message. diff --git a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/FeatureToggleControllerTests.cs b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/FeatureToggleControllerTests.cs index 0347e60..f84affb 100644 --- a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/FeatureToggleControllerTests.cs +++ b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/FeatureToggleControllerTests.cs @@ -23,11 +23,11 @@ public async Task GetAllFeatureToggles() { Id = 2, Feature = "bye", IsEnabled = false } ); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Make the call and ensure it's successful. var controller = new FeatureToggleController(_db); - ObjectResult obj = await controller.GetAll(); + ObjectResult obj = await controller.GetAll().ConfigureAwait(false); Assert.That(obj.StatusCode, Is.EqualTo(200)); // Ensure they passed through cleanly. diff --git a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/UserControllerTests.cs b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/UserControllerTests.cs index 3b810de..258fa27 100644 --- a/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/UserControllerTests.cs +++ b/src/Nullinside.Api.Tests/Nullinside.Api/Controllers/UserControllerTests.cs @@ -65,12 +65,12 @@ public async Task PerformGoogleLoginExisting() { Email = "hi" }); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); controller.Email = "hi"; - RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }); + RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }).ConfigureAwait(false); // We should have been redirected to the successful route. Assert.That(obj.Url.StartsWith("/user/login?token="), Is.True); @@ -90,7 +90,7 @@ public async Task PerformGoogleLoginNewUser() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); controller.Email = "hi"; - RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }); + RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }).ConfigureAwait(false); // We should have been redirected to the successful route. Assert.That(obj.Url.StartsWith("/user/login?token="), Is.True); @@ -112,7 +112,7 @@ public async Task GoToErrorOnDbException() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); controller.Email = "hi"; - RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }); + RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }).ConfigureAwait(false); // We should have been redirected to the error. Assert.That(obj.Url.StartsWith("/user/login?error="), Is.True); @@ -126,7 +126,7 @@ public async Task GoToErrorOnBadGmailResponse() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); controller.Email = null; - RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }); + RedirectResult obj = await controller.Login(new GoogleOpenIdToken { credential = "stuff" }).ConfigureAwait(false); // We should have been redirected to the error. Assert.That(obj.Url.StartsWith("/user/login?error="), Is.True); @@ -151,11 +151,11 @@ public async Task PerformTwitchLoginExisting() { Email = "hi" }); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object); + RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object).ConfigureAwait(false); // We should have been redirected to the successful route. Assert.That(obj.Url.StartsWith("/user/login?token="), Is.True); @@ -182,7 +182,7 @@ public async Task PerformTwitchLoginNewUser() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object); + RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object).ConfigureAwait(false); // We should have been redirected to the successful route. Assert.That(obj.Url.StartsWith("/user/login?token="), Is.True); @@ -205,7 +205,7 @@ public async Task PerformTwitchLoginBadTwitchResponse() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object); + RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object).ConfigureAwait(false); // We should have gone down the bad route Assert.That(obj.Url.StartsWith("/user/login?error="), Is.True); @@ -222,7 +222,7 @@ public async Task PerformTwitchLoginWithNoEmailAccount() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object); + RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object).ConfigureAwait(false); // We should have gone down the bad route because no email was associated with the twitch account. Assert.That(obj.Url.StartsWith("/user/login?error="), Is.True); @@ -245,7 +245,7 @@ public async Task PerformTwitchLoginDbFailure() { // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object); + RedirectResult obj = await controller.TwitchLogin("things", _twitchApi.Object).ConfigureAwait(false); // We should have been redirected to the error route because of an exception in DB processing. Assert.That(obj.Url.StartsWith("/user/login?error="), Is.True); @@ -283,11 +283,11 @@ public void GetRoles() { [Test] public async Task ValidateTokenExists() { _db.Users.Add(new User { Token = "123" }); - await _db.SaveChangesAsync(); + await _db.SaveChangesAsync().ConfigureAwait(false); // Make the call and ensure it's successful. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - IActionResult obj = await controller.Validate(new AuthToken("123")); + IActionResult obj = await controller.Validate(new AuthToken("123")).ConfigureAwait(false); Assert.That((obj as IStatusCodeActionResult)?.StatusCode, Is.EqualTo(200)); // Ensure we returned that the token was correct. @@ -301,7 +301,7 @@ public async Task ValidateTokenExists() { public async Task ValidateFailWithoutToken() { // Make the call and ensure it fails. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - IActionResult obj = await controller.Validate(new AuthToken("123")); + IActionResult obj = await controller.Validate(new AuthToken("123")).ConfigureAwait(false); Assert.That((obj as IStatusCodeActionResult)?.StatusCode, Is.EqualTo(401)); } @@ -314,7 +314,7 @@ public async Task ValidateFailOnDbFailure() { // Make the call and ensure it fails. var controller = new TestableUserController(_configuration, _db, _webSocketPersister.Object); - IActionResult obj = await controller.Validate(new AuthToken("123")); + IActionResult obj = await controller.Validate(new AuthToken("123")).ConfigureAwait(false); Assert.That((obj as IStatusCodeActionResult)?.StatusCode, Is.EqualTo(500)); } } diff --git a/src/Nullinside.Api.Tests/UnitTestBase.cs b/src/Nullinside.Api.Tests/UnitTestBase.cs index ebc3f16..63f1e82 100644 --- a/src/Nullinside.Api.Tests/UnitTestBase.cs +++ b/src/Nullinside.Api.Tests/UnitTestBase.cs @@ -28,6 +28,6 @@ public virtual void Setup() { [TearDown] public virtual async Task TearDown() { // Dispose since it has one. - await _db.DisposeAsync(); + await _db.DisposeAsync().ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/Nullinside.Api/Controllers/DatabaseController.cs b/src/Nullinside.Api/Controllers/DatabaseController.cs index 65a2847..4ff7f92 100644 --- a/src/Nullinside.Api/Controllers/DatabaseController.cs +++ b/src/Nullinside.Api/Controllers/DatabaseController.cs @@ -43,7 +43,7 @@ public DatabaseController(INullinsideContext dbContext) { [HttpGet] [Route("migration")] public async Task Migrate() { - await _dbContext.Database.MigrateAsync(); + await _dbContext.Database.MigrateAsync().ConfigureAwait(false); return Ok(); } } \ No newline at end of file diff --git a/src/Nullinside.Api/Controllers/DockerController.cs b/src/Nullinside.Api/Controllers/DockerController.cs index 756994c..d0ba92e 100644 --- a/src/Nullinside.Api/Controllers/DockerController.cs +++ b/src/Nullinside.Api/Controllers/DockerController.cs @@ -61,7 +61,7 @@ public DockerController(INullinsideContext dbContext, IDockerProxy dockerProxy) Task> recognizedProjects = _dbContext.DockerDeployments.ToListAsync(token); // Wait for all the async calls to finish. - await Task.WhenAll(containers, projects, recognizedProjects); + await Task.WhenAll(containers, projects, recognizedProjects).ConfigureAwait(false); // Map the output var response = new List(); @@ -96,7 +96,7 @@ public DockerController(INullinsideContext dbContext, IDockerProxy dockerProxy) public async Task TurnOnOrOffDockerResources(int id, TurnOnOrOffDockerResourcesRequest request, CancellationToken token = new()) { DockerDeployments? recognizedProjects = await _dbContext.DockerDeployments - .FirstOrDefaultAsync(d => d.Id == id, token); + .FirstOrDefaultAsync(d => d.Id == id, token).ConfigureAwait(false); if (null == recognizedProjects) { return BadRequest(new BasicServerFailure("'id' is invalid")); } @@ -104,10 +104,10 @@ public async Task TurnOnOrOffDockerResources(int id, TurnOnOrOffDo bool result; if (recognizedProjects.IsDockerComposeProject) { result = await _docker.TurnOnOffDockerCompose(recognizedProjects.Name, request.TurnOn, token, - recognizedProjects.ServerDir); + recognizedProjects.ServerDir).ConfigureAwait(false); } else { - result = await _docker.TurnOnOffDockerContainer(recognizedProjects.Name, request.TurnOn, token); + result = await _docker.TurnOnOffDockerContainer(recognizedProjects.Name, request.TurnOn, token).ConfigureAwait(false); } return Ok(result); diff --git a/src/Nullinside.Api/Controllers/FeatureToggleController.cs b/src/Nullinside.Api/Controllers/FeatureToggleController.cs index a1732b7..1847111 100644 --- a/src/Nullinside.Api/Controllers/FeatureToggleController.cs +++ b/src/Nullinside.Api/Controllers/FeatureToggleController.cs @@ -40,6 +40,6 @@ public FeatureToggleController(INullinsideContext dbContext) { [AllowAnonymous] [HttpGet] public async Task GetAll(CancellationToken token = new()) { - return Ok(await _dbContext.FeatureToggle.ToListAsync(token)); + return Ok(await _dbContext.FeatureToggle.ToListAsync(token).ConfigureAwait(false)); } } \ No newline at end of file diff --git a/src/Nullinside.Api/Controllers/UserController.cs b/src/Nullinside.Api/Controllers/UserController.cs index 68f47dd..5947b9b 100644 --- a/src/Nullinside.Api/Controllers/UserController.cs +++ b/src/Nullinside.Api/Controllers/UserController.cs @@ -1,6 +1,5 @@ using System.Net.WebSockets; using System.Security.Claims; -using System.Text; using Google.Apis.Auth; @@ -73,12 +72,12 @@ public UserController(IConfiguration configuration, INullinsideContext dbContext public async Task Login([FromForm] GoogleOpenIdToken creds, CancellationToken token = new()) { string? siteUrl = _configuration.GetValue("Api:SiteUrl"); try { - GoogleJsonWebSignature.Payload? credentials = await GenerateUserObject(creds); + GoogleJsonWebSignature.Payload? credentials = await GenerateUserObject(creds).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(credentials?.Email)) { return Redirect($"{siteUrl}/user/login?error=1"); } - string? bearerToken = await UserHelpers.GenerateTokenAndSaveToDatabase(_dbContext, credentials.Email, token); + string? bearerToken = await UserHelpers.GenerateTokenAndSaveToDatabase(_dbContext, credentials.Email, token).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(bearerToken)) { return Redirect($"{siteUrl}/user/login?error=2"); } @@ -96,7 +95,7 @@ public UserController(IConfiguration configuration, INullinsideContext dbContext /// The credentials from Google. /// The user information object. protected virtual async Task GenerateUserObject(GoogleOpenIdToken creds) { - return await GoogleJsonWebSignature.ValidateAsync(creds.credential); + return await GoogleJsonWebSignature.ValidateAsync(creds.credential).ConfigureAwait(false); } /// @@ -119,16 +118,16 @@ public UserController(IConfiguration configuration, INullinsideContext dbContext public async Task TwitchLogin([FromQuery] string code, [FromServices] ITwitchApiProxy api, CancellationToken token = new()) { string? siteUrl = _configuration.GetValue("Api:SiteUrl"); - if (null == await api.CreateAccessToken(code, token)) { + if (null == await api.CreateAccessToken(code, token).ConfigureAwait(false)) { return Redirect($"{siteUrl}/user/login?error=3"); } - string? email = await api.GetUserEmail(token); + string? email = await api.GetUserEmail(token).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(email)) { return Redirect($"{siteUrl}/user/login?error=4"); } - string? bearerToken = await UserHelpers.GenerateTokenAndSaveToDatabase(_dbContext, email, token); + string? bearerToken = await UserHelpers.GenerateTokenAndSaveToDatabase(_dbContext, email, token).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(bearerToken)) { return Redirect($"{siteUrl}/user/login?error=2"); } @@ -163,7 +162,7 @@ public async Task TwitchStreamingToolsLogin([FromQuery] string c } // Since someone already warned us this request was coming, create an oauth token from the code we received. - if (null == await api.CreateAccessToken(code, token)) { + if (null == await api.CreateAccessToken(code, token).ConfigureAwait(false)) { return Redirect($"{siteUrl}/user/login/desktop?error=2"); } @@ -177,8 +176,8 @@ public async Task TwitchStreamingToolsLogin([FromQuery] string c ExpiresUtc = api.OAuth?.ExpiresUtc ?? DateTime.MinValue }; - await socket.SendTextAsync(JsonConvert.SerializeObject(oAuth), token); - await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Completed Successfully!", token); + await socket.SendTextAsync(JsonConvert.SerializeObject(oAuth), token).ConfigureAwait(false); + await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Completed Successfully!", token).ConfigureAwait(false); _webSockets.WebSockets.TryRemove(state, out _); socket.Dispose(); } @@ -199,11 +198,11 @@ public async Task TwitchStreamingToolsLogin([FromQuery] string c public async Task TwitchStreamingToolsRefreshToken(CancellationToken token = new()) { if (HttpContext.WebSockets.IsWebSocketRequest) { // Connect with the client - using WebSocket webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); + using WebSocket webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false); // The first communication over the web socket is always the id that we will later get from the // twitch api with the associated credentials. - string id = await webSocket.ReceiveTextAsync(token); + string id = await webSocket.ReceiveTextAsync(token).ConfigureAwait(false); id = id.Trim(); // Add the web socket to web socket persistant service. It will be sitting there until the twitch api calls our @@ -214,7 +213,7 @@ public async Task TwitchStreamingToolsLogin([FromQuery] string c // lose the connection. That's just the way web sockets are implemented in .NET Core Web APIs. So we have to sit // here in an await (specifically in an await so we don't mess up the thread pool) until twitch calls us. while (null == webSocket.CloseStatus) { - await Task.Delay(1000, token); + await Task.Delay(1000, token).ConfigureAwait(false); } } else { @@ -239,7 +238,7 @@ public async Task TwitchStreamingToolsRefreshToken([FromForm] str ExpiresUtc = DateTime.MinValue }; - if (null == await api.RefreshAccessToken(token)) { + if (null == await api.RefreshAccessToken(token).ConfigureAwait(false)) { return BadRequest(); } @@ -281,7 +280,7 @@ from claim in identify.Claims [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task Validate(AuthToken token, CancellationToken cancellationToken = new()) { try { - User? existing = await _dbContext.Users.FirstOrDefaultAsync(u => u.Token == token.Token && !u.IsBanned, cancellationToken); + User? existing = await _dbContext.Users.FirstOrDefaultAsync(u => u.Token == token.Token && !u.IsBanned, cancellationToken).ConfigureAwait(false); if (null == existing) { return Unauthorized(); } diff --git a/src/Nullinside.Api/Nullinside.Api.csproj.DotSettings b/src/Nullinside.Api/Nullinside.Api.csproj.DotSettings index 89316e4..4527ed0 100644 --- a/src/Nullinside.Api/Nullinside.Api.csproj.DotSettings +++ b/src/Nullinside.Api/Nullinside.Api.csproj.DotSettings @@ -1,2 +1,4 @@ - + Library \ No newline at end of file