diff --git a/.github/workflows/ci-suite.yml b/.github/workflows/ci-suite.yml index 2e7e1adcec..dcd508aaf5 100644 --- a/.github/workflows/ci-suite.yml +++ b/.github/workflows/ci-suite.yml @@ -57,44 +57,6 @@ jobs: - name: GitHub Requires at Least One Step for a Job run: exit 0 - analyze: - name: Code Scanning - needs: start-ci-run-gate - if: "!(cancelled() || failure()) && needs.start-ci-run-gate.result == 'success'" - runs-on: ubuntu-latest - steps: - - name: Install Node 12.X - uses: actions/setup-node@v3 - with: - node-version: 12.x - - - name: Upgrade NPM - run: npm install -g npm - - - name: Checkout (Branch) - uses: actions/checkout@v3 - if: github.event_name == 'push' || github.event_name == 'schedule' - with: - fetch-depth: 2 - - - name: Checkout (PR Merge) - uses: actions/checkout@v3 - if: github.event_name != 'push' && github.event_name != 'schedule' - with: - fetch-depth: 2 - ref: "refs/pull/${{ github.event.number }}/merge" - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: csharp - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - dmapi-build: name: Build DMAPI needs: start-ci-run-gate @@ -114,7 +76,7 @@ jobs: uses: actions/cache@v3 id: cache-byond with: - path: $HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }} + path: ~/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }} key: ${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }}-dmapibyond - name: Install BYOND @@ -338,7 +300,7 @@ jobs: uses: actions/cache@v3 id: cache-byond with: - path: $HOME/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }} + path: ~/BYOND-${{ env.BYOND_MAJOR }}.${{ env.BYOND_MINOR }} key: ${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }}-livebyond - name: Download BYOND diff --git a/.github/workflows/code-scanning.yml b/.github/workflows/code-scanning.yml new file mode 100644 index 0000000000..4118c5b1cf --- /dev/null +++ b/.github/workflows/code-scanning.yml @@ -0,0 +1,44 @@ +name: 'Code Scanning' + +on: + schedule: + - cron: 0 23 * * * + push: + branches: + - dev + - master + pull_request: + branches: + - dev + - master + +concurrency: + group: "code-scanning-${{ github.head_ref || github.run_id }}-${{ github.event_name }}" + cancel-in-progress: true + +jobs: + analyze: + name: Code Scanning + runs-on: ubuntu-latest + steps: + - name: Install Node 12.X + uses: actions/setup-node@v3 + with: + node-version: 12.x + + - name: Upgrade NPM + run: npm install -g npm + + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: csharp + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs index df32ce6e48..75fe7bcd47 100644 --- a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs +++ b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs @@ -70,8 +70,7 @@ namespace Tgstation.Server.Host.Components.Byond IOManager.ConcatPath( PathToUserByondFolder, CacheDirectoryName), - cancellationToken) - ; + cancellationToken); } catch (OperationCanceledException) { diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs index 08d4b7a1ce..e8db69db69 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs @@ -383,8 +383,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, TaskScheduler.Current) - .WithToken(cancellationToken) - ; + .WithToken(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); @@ -480,8 +479,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); await HardDisconnect(cancellationToken); } catch (OperationCanceledException) diff --git a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs index 7d57085eff..2c5abb0541 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs @@ -145,8 +145,7 @@ namespace Tgstation.Server.Host.Components.Deployment job); await remoteDeploymentManager.StageDeployment( newProvider.CompileJob, - cancellationToken) - ; + cancellationToken); } lock (jobLockCounts) @@ -188,10 +187,8 @@ namespace Tgstation.Server.Host.Components.Deployment .AsQueryable() .Where(x => x.Job.Instance.Id == metadata.Id) .OrderByDescending(x => x.Job.StoppedAt) - .FirstOrDefaultAsync(cancellationToken) - ; - }) - ; + .FirstOrDefaultAsync(cancellationToken); + }); if (cj == default(CompileJob)) return; @@ -267,8 +264,7 @@ namespace Tgstation.Server.Host.Components.Deployment ioManager.ConcatPath( newProvider.Directory, newProvider.DmbName), - cancellationToken) - ; + cancellationToken); if (!dmbExistsAtRoot) { diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index 8470210425..31e8e3a956 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -241,8 +241,7 @@ namespace Tgstation.Server.Host.Components.Deployment StartupTimeout = x.StartupTimeout, LogOutput = x.LogOutput, }) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (ddSettings == default) throw new JobException(ErrorCode.InstanceMissingDreamDaemonSettings); @@ -250,8 +249,7 @@ namespace Tgstation.Server.Host.Components.Deployment .DreamMakerSettings .AsQueryable() .Where(x => x.InstanceId == metadata.Id) - .FirstAsync(cancellationToken) - ; + .FirstAsync(cancellationToken); if (dreamMakerSettings == default) throw new JobException(ErrorCode.InstanceMissingDreamMakerSettings); @@ -267,8 +265,7 @@ namespace Tgstation.Server.Host.Components.Deployment PushTestMergeCommits = x.PushTestMergeCommits, PostTestMergeComment = x.PostTestMergeComment, }) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (repositorySettings == default) throw new JobException(ErrorCode.InstanceMissingRepositorySettings); @@ -291,8 +288,7 @@ namespace Tgstation.Server.Host.Components.Deployment .Include(x => x.ActiveTestMerges) .ThenInclude(x => x.TestMerge) .ThenInclude(x => x.MergedBy) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (revInfo == default) { @@ -319,8 +315,7 @@ namespace Tgstation.Server.Host.Components.Deployment repo?.Dispose(); throw; } - }) - ; + }); var likelyPushedTestMergeCommit = repositorySettings.PushTestMergeCommits.Value @@ -336,8 +331,7 @@ namespace Tgstation.Server.Host.Components.Deployment progressReporter, averageSpan, likelyPushedTestMergeCommit, - cancellationToken) - ; + cancellationToken); var activeCompileJob = compileJobConsumer.LatestCompileJob(); try @@ -379,8 +373,7 @@ namespace Tgstation.Server.Host.Components.Deployment compileJob.Job = fullJob; compileJob.RevisionInformation = fullRevInfo; - }) - ; + }); } catch (Exception ex) { @@ -447,8 +440,7 @@ namespace Tgstation.Server.Host.Components.Deployment StoppedAt = x.Job.StoppedAt, StartedAt = x.Job.StartedAt, }) - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); TimeSpan? averageSpan = null; if (previousCompileJobs.Count != 0) @@ -605,8 +597,7 @@ namespace Tgstation.Server.Host.Components.Deployment repoOrigin.ToString(), $"{byondLock.Version.Major}.{byondLock.Version.Minor}", }, - cancellationToken) - ; + cancellationToken); // determine the dme progressReporter.StageName = "Determining .dme"; @@ -978,8 +969,7 @@ namespace Tgstation.Server.Host.Components.Deployment remoteDeploymentManager.FailDeployment( job, FormatExceptionForUsers(exception), - default)) - ; + default)); } } } diff --git a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs index 0acc80828c..a794135d13 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs @@ -73,8 +73,7 @@ namespace Tgstation.Server.Host.Components.Deployment await symlinkFactory.CreateSymbolicLink( ioManager.ResolvePath(baseProvider.Directory), ioManager.ResolvePath(LiveGameDirectory), - cancellationToken) - ; + cancellationToken); } } } diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index 0e441edb15..42e18fa43b 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -185,8 +185,7 @@ namespace Tgstation.Server.Host.Components Configuration.StartAsync(cancellationToken), ByondManager.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), - dmbFactory.StartAsync(cancellationToken)) - ; + dmbFactory.StartAsync(cancellationToken)); // dependent on so many things, its just safer this way await Watchdog.StartAsync(cancellationToken); @@ -310,8 +309,7 @@ namespace Tgstation.Server.Host.Components repositorySettings.AccessUser, repositorySettings.AccessToken, NextProgressReporter("Fetch Origin"), - cancellationToken) - ; + cancellationToken); var hasDbChanges = false; RevisionInformation currentRevInfo = null; @@ -385,8 +383,7 @@ namespace Tgstation.Server.Host.Components repositorySettings.CommitterName, repositorySettings.CommitterEmail, NextProgressReporter("Merge Origin"), - cancellationToken) - ; + cancellationToken); var preserveTestMerges = repositorySettings.AutoUpdatesKeepTestMerges.Value; var remoteDeploymentManager = remoteDeploymentManagerFactory.CreateRemoteDeploymentManager( @@ -435,16 +432,14 @@ namespace Tgstation.Server.Host.Components repositorySettings.AccessToken, repositorySettings.UpdateSubmodules.Value, NextProgressReporter(StageName), - cancellationToken) - ; + cancellationToken); var currentHead = repo.Head; currentRevInfo = await databaseContext.RevisionInformations .AsQueryable() .Where(x => x.CommitSha == currentHead && x.Instance.Id == metadata.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentHead != startSha && currentRevInfo == default) await UpdateRevInfo(currentHead, true, null); @@ -555,8 +550,7 @@ namespace Tgstation.Server.Host.Components progressReporter, jobCancellationToken); }, - cancellationToken) - ; + cancellationToken); } await jobManager.WaitForJobCompletion(compileProcessJob, null, default, cancellationToken); diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs index a0c7f8ceec..1ffb944912 100644 --- a/src/Tgstation.Server.Host/Components/InstanceManager.cs +++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs @@ -284,8 +284,7 @@ namespace Tgstation.Server.Host.Components await ioManager.WriteAllBytes( ioManager.ConcatPath(oldPath, InstanceController.InstanceAttachFileName), Array.Empty(), - default) - ; + default); } catch (Exception tripleEx) { diff --git a/src/Tgstation.Server.Host/Components/Repository/GitLabRemoteFeatures.cs b/src/Tgstation.Server.Host/Components/Repository/GitLabRemoteFeatures.cs index b66c98f3e1..fbb43a62ef 100644 --- a/src/Tgstation.Server.Host/Components/Repository/GitLabRemoteFeatures.cs +++ b/src/Tgstation.Server.Host/Components/Repository/GitLabRemoteFeatures.cs @@ -66,8 +66,7 @@ namespace Tgstation.Server.Host.Components.Repository var mr = await client .MergeRequests .GetAsync($"{RemoteRepositoryOwner}/{RemoteRepositoryName}", parameters.Number) - .WithToken(cancellationToken) - ; + .WithToken(cancellationToken); var revisionToUse = parameters.TargetCommitSha == null || mr.Sha.StartsWith(parameters.TargetCommitSha, StringComparison.OrdinalIgnoreCase) diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs index 6025be0cff..f0256c05e1 100644 --- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs +++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs @@ -356,8 +356,7 @@ namespace Tgstation.Server.Host.Components.Repository }), cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); if (updateSubmodules) { @@ -412,8 +411,7 @@ namespace Tgstation.Server.Host.Components.Repository }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); if (updateSubmodules) await UpdateSubmodules( @@ -463,8 +461,7 @@ namespace Tgstation.Server.Host.Components.Repository }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); } /// @@ -485,8 +482,7 @@ namespace Tgstation.Server.Host.Components.Repository await ResetToSha( trackedBranch.Tip.Sha, progressReporter.CreateSection(null, updateSubmodules ? 2.0 / 3 : 1.0), - cancellationToken) - ; + cancellationToken); if (updateSubmodules) await UpdateSubmodules( @@ -619,8 +615,7 @@ namespace Tgstation.Server.Host.Components.Repository }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); if (result.Status == MergeStatus.Conflicts) { @@ -684,8 +679,7 @@ namespace Tgstation.Server.Host.Components.Repository { ioMananger.ResolvePath(), }, - cancellationToken) - ; + cancellationToken); } finally { @@ -702,8 +696,7 @@ namespace Tgstation.Server.Host.Components.Repository }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); } var remainingProgressFactor = 0.9; @@ -759,8 +752,7 @@ namespace Tgstation.Server.Host.Components.Repository }, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, - TaskScheduler.Current) - ; + TaskScheduler.Current); } /// @@ -1040,8 +1032,7 @@ namespace Tgstation.Server.Host.Components.Repository await Task.WhenAll( ioMananger.DeleteDirectory($".git/modules/{submodule.Path}", cancellationToken), - ioMananger.DeleteDirectory(submodule.Path, cancellationToken)) - ; + ioMananger.DeleteDirectory(submodule.Path, cancellationToken)); logger.LogTrace("Second update attempt for submodule {submoduleName}...", submodule.Name); try diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs index 4f283079de..53de9c45c3 100644 --- a/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs +++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryUpdateService.cs @@ -270,8 +270,7 @@ namespace Tgstation.Server.Host.Components.Repository currentModel.CommitterEmail, NextProgressReporter("Sychronize"), true, - cancellationToken) - ; + cancellationToken); postUpdateSha = repo.Head; } else @@ -305,8 +304,7 @@ namespace Tgstation.Server.Host.Components.Repository currentModel.AccessToken, updateSubmodules, NextProgressReporter("Checkout"), - cancellationToken) - ; + cancellationToken); await CallLoadRevInfo(); // we've either seen origin before or what we're checking out is on origin } else @@ -321,8 +319,7 @@ namespace Tgstation.Server.Host.Components.Repository currentModel.AccessToken, updateSubmodules, NextProgressReporter("Reset to Origin"), - cancellationToken) - ; + cancellationToken); await repo.Sychronize( currentModel.AccessUser, currentModel.AccessToken, @@ -330,8 +327,7 @@ namespace Tgstation.Server.Host.Components.Repository currentModel.CommitterEmail, NextProgressReporter("Synchronize"), true, - cancellationToken) - ; + cancellationToken); await CallLoadRevInfo(); // repo head is on origin so force this @@ -545,8 +541,7 @@ namespace Tgstation.Server.Host.Components.Repository currentModel.CommitterEmail, NextProgressReporter("Synchronize"), false, - cancellationToken) - ; + cancellationToken); await UpdateRevInfo(); } diff --git a/src/Tgstation.Server.Host/Components/Session/SessionController.cs b/src/Tgstation.Server.Host/Components/Session/SessionController.cs index 164fb6e218..b7978ff051 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionController.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionController.cs @@ -444,8 +444,7 @@ namespace Tgstation.Server.Host.Components.Session { var commandResult = await SendCommand( new TopicParameters(port), - cancellationToken) - ; + cancellationToken); if (commandResult?.ErrorMessage != null) return false; @@ -478,8 +477,7 @@ namespace Tgstation.Server.Host.Components.Session ReattachInformation.RebootState = newRebootState; var result = await SendCommand( new TopicParameters(newRebootState), - cancellationToken) - ; + cancellationToken); return result?.ErrorMessage == null; } diff --git a/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs b/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs index 34b46db93c..6b1020fd92 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionPersistor.cs @@ -140,8 +140,7 @@ namespace Tgstation.Server.Host.Components.Session .AsQueryable() .Where(x => x.Id == metadata.Id) .Select(x => x.DreamDaemonSettings.TopicRequestTimeout) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (timeoutMilliseconds == default) { @@ -238,8 +237,7 @@ namespace Tgstation.Server.Host.Components.Session if (instant) await baseQuery - .DeleteAsync(cancellationToken) - ; + .DeleteAsync(cancellationToken); else { var results = await baseQuery.ToListAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index 3ba224a038..55a8aba459 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -652,8 +652,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles await Task.WhenAll( ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken), ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken), - ValidateStaticFolder()) - ; + ValidateStaticFolder()); } /// diff --git a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs index f9f3e6bbb4..9eacfc2f17 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/PosixWatchdog.cs @@ -102,8 +102,7 @@ namespace Tgstation.Server.Host.Components.Watchdog await GameIOManager.MoveDirectory( ActiveSwappable.CompileJob.DirectoryName.ToString(), ActiveSwappable.Directory, - cancellationToken) - ; + cancellationToken); hardLinkedDmb = ActiveSwappable; } @@ -131,8 +130,7 @@ namespace Tgstation.Server.Host.Components.Watchdog await GameIOManager.MoveDirectory( hardLink, originalPosition, - default) - ; + default); } catch (Exception ex) { diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs index 07e0ebbe89..4a748ee869 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs @@ -465,8 +465,7 @@ namespace Tgstation.Server.Host.Components.Watchdog var notification = new EventNotification(eventType, parameters); var result = await activeServer.SendCommand( new TopicParameters(notification), - cancellationToken) - ; + cancellationToken); HandleChatResponses(result); } diff --git a/src/Tgstation.Server.Host/Controllers/ApiController.cs b/src/Tgstation.Server.Host/Controllers/ApiController.cs index c563525265..46c9730b4c 100644 --- a/src/Tgstation.Server.Host/Controllers/ApiController.cs +++ b/src/Tgstation.Server.Host/Controllers/ApiController.cs @@ -122,8 +122,7 @@ namespace Tgstation.Server.Host.Controllers await StatusCode( HttpStatusCode.UpgradeRequired, new ErrorMessageResponse(ErrorCode.ApiMismatch)) - .ExecuteResultAsync(context) - ; + .ExecuteResultAsync(context); return; } @@ -139,8 +138,7 @@ namespace Tgstation.Server.Host.Controllers if (requireHeaders) { await HeadersIssue(false) - .ExecuteResultAsync(context) - ; + .ExecuteResultAsync(context); return; } } @@ -221,8 +219,13 @@ namespace Tgstation.Server.Host.Controllers /// /// Generic 501 response. /// + /// The that was thrown. /// An with . - protected ObjectResult RequiresPosixSystemIdentity() => StatusCode(HttpStatusCode.NotImplemented, new ErrorMessageResponse(ErrorCode.RequiresPosixSystemIdentity)); + protected ObjectResult RequiresPosixSystemIdentity(NotImplementedException ex) + { + Logger.LogTrace(ex, "System identities not implemented!"); + return StatusCode(HttpStatusCode.NotImplemented, new ErrorMessageResponse(ErrorCode.RequiresPosixSystemIdentity)); + } /// /// Strongly type calls to . @@ -395,8 +398,7 @@ namespace Tgstation.Server.Host.Controllers { totalResults = await paginationResult.Results.CountAsync(cancellationToken); pagedResults = await queriedResults - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); } else { diff --git a/src/Tgstation.Server.Host/Controllers/ChatController.cs b/src/Tgstation.Server.Host/Controllers/ChatController.cs index d4651d1877..0b09b786ae 100644 --- a/src/Tgstation.Server.Host/Controllers/ChatController.cs +++ b/src/Tgstation.Server.Host/Controllers/ChatController.cs @@ -188,8 +188,7 @@ namespace Tgstation.Server.Host.Controllers .ChatBots .AsQueryable() .Where(x => x.Id == id) - .DeleteAsync(cancellationToken)) - ; + .DeleteAsync(cancellationToken)); return null; }) @@ -364,8 +363,7 @@ namespace Tgstation.Server.Host.Controllers await chat.ChangeChannels(current.Id.Value, current.Channels, cancellationToken); return null; - }) - ; + }); if (earlyOut != null) return earlyOut; diff --git a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs index cc401330f4..b563293511 100644 --- a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs +++ b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs @@ -84,12 +84,10 @@ namespace Tgstation.Server.Host.Controllers model.Path, systemIdentity, model.LastReadHash, - cancellationToken) - ; + cancellationToken); return model.LastReadHash == null ? Accepted(newFile) : Json(newFile); - }) - ; + }); } catch (IOException e) { @@ -99,9 +97,9 @@ namespace Tgstation.Server.Host.Controllers AdditionalData = e.Message, }); } - catch (NotImplementedException) + catch (NotImplementedException ex) { - return RequiresPosixSystemIdentity(); + return RequiresPosixSystemIdentity(ex); } } @@ -129,14 +127,12 @@ namespace Tgstation.Server.Host.Controllers { var result = await instance .Configuration - .Read(filePath, systemIdentity, cancellationToken) - ; + .Read(filePath, systemIdentity, cancellationToken); if (result == null) return Gone(); return Json(result); - }) - ; + }); } catch (IOException e) { @@ -146,9 +142,9 @@ namespace Tgstation.Server.Host.Controllers AdditionalData = e.Message, }); } - catch (NotImplementedException) + catch (NotImplementedException ex) { - return RequiresPosixSystemIdentity(); + return RequiresPosixSystemIdentity(ex); } } @@ -183,8 +179,7 @@ namespace Tgstation.Server.Host.Controllers { var result = await instance .Configuration - .ListDirectory(directoryPath, systemIdentity, cancellationToken) - ; + .ListDirectory(directoryPath, systemIdentity, cancellationToken); if (result == null) return new PaginatableResult(Gone()); @@ -193,10 +188,10 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .OrderBy(x => x.Path)); } - catch (NotImplementedException) + catch (NotImplementedException ex) { return new PaginatableResult( - RequiresPosixSystemIdentity()); + RequiresPosixSystemIdentity(ex)); } catch (UnauthorizedAccessException) { @@ -257,8 +252,7 @@ namespace Tgstation.Server.Host.Controllers .Configuration .CreateDirectory(model.Path, systemIdentity, cancellationToken) ? Json(resultModel) - : Created(resultModel)) - ; + : Created(resultModel)); } catch (IOException e) { @@ -268,9 +262,9 @@ namespace Tgstation.Server.Host.Controllers Message = e.Message, }); } - catch (NotImplementedException) + catch (NotImplementedException ex) { - return RequiresPosixSystemIdentity(); + return RequiresPosixSystemIdentity(ex); } catch (UnauthorizedAccessException) { @@ -308,9 +302,9 @@ namespace Tgstation.Server.Host.Controllers ? NoContent() : Conflict(new ErrorMessageResponse(ErrorCode.ConfigurationDirectoryNotEmpty))); } - catch (NotImplementedException) + catch (NotImplementedException ex) { - return RequiresPosixSystemIdentity(); + return RequiresPosixSystemIdentity(ex); } catch (UnauthorizedAccessException) { diff --git a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs index 98db93e527..a2f516b560 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs @@ -94,8 +94,7 @@ namespace Tgstation.Server.Host.Controllers await jobManager.RegisterOperation( job, (core, databaseContextFactory, paramJob, progressHandler, innerCt) => core.Watchdog.Launch(innerCt), - cancellationToken) - ; + cancellationToken); return Accepted(job.ToApi()); }); @@ -241,8 +240,7 @@ namespace Tgstation.Server.Host.Controllers await watchdog.ResetRebootState(cancellationToken); return await ReadImpl(current, cancellationToken); - }) - ; + }); } #pragma warning restore CA1506 #pragma warning restore CA1502 @@ -276,8 +274,7 @@ namespace Tgstation.Server.Host.Controllers await jobManager.RegisterOperation( job, (core, paramJob, databaseContextFactory, progressReporter, ct) => core.Watchdog.Restart(false, ct), - cancellationToken) - ; + cancellationToken); return Accepted(job.ToApi()); }); @@ -310,8 +307,7 @@ namespace Tgstation.Server.Host.Controllers await jobManager.RegisterOperation( job, (core, databaseContextFactory, paramJob, progressReporter, ct) => core.Watchdog.CreateDump(ct), - cancellationToken) - ; + cancellationToken); return Accepted(job.ToApi()); }); @@ -336,8 +332,7 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .Where(x => x.Id == Instance.Id) .Select(x => x.DreamDaemonSettings) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (settings == default) return Gone(); } diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs index acd862ee72..60a99ef797 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs @@ -79,8 +79,7 @@ namespace Tgstation.Server.Host.Controllers .DreamMakerSettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); return Json(dreamMakerSettings.ToApi()); } @@ -152,8 +151,7 @@ namespace Tgstation.Server.Host.Controllers job, (core, databaseContextFactory, paramJob, progressReporter, jobCancellationToken) => core.DreamMaker.DeploymentProcess(paramJob, databaseContextFactory, progressReporter, jobCancellationToken), - cancellationToken) - ; + cancellationToken); return Accepted(job.ToApi()); } @@ -188,8 +186,7 @@ namespace Tgstation.Server.Host.Controllers .DreamMakerSettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (hostModel == null) return Gone(); @@ -214,8 +211,7 @@ namespace Tgstation.Server.Host.Controllers .GetAvailablePort( model.ApiValidationPort.Value, true, - cancellationToken) - ; + cancellationToken); if (verifiedPort != model.ApiValidationPort) return Conflict(new ErrorMessageResponse(ErrorCode.PortNotAvailable)); diff --git a/src/Tgstation.Server.Host/Controllers/HomeController.cs b/src/Tgstation.Server.Host/Controllers/HomeController.cs index ac9e666be8..731be3182f 100644 --- a/src/Tgstation.Server.Host/Controllers/HomeController.cs +++ b/src/Tgstation.Server.Host/Controllers/HomeController.cs @@ -241,7 +241,7 @@ namespace Tgstation.Server.Host.Controllers } catch (NotImplementedException ex) { - Logger.LogTrace(ex, "System identities not implemented!"); + RequiresPosixSystemIdentity(ex); } using (systemIdentity) @@ -297,6 +297,7 @@ namespace Tgstation.Server.Host.Controllers PasswordHash = x.PasswordHash, Enabled = x.Enabled, Name = x.Name, + SystemIdentifier = x.SystemIdentifier, }) .ToListAsync(cancellationToken); @@ -315,13 +316,13 @@ namespace Tgstation.Server.Host.Controllers // FALLBACK TO THE DB USER HERE, DO NOT REVEAL A SYSTEM LOGIN!!! // This of course, allows system users to discover TGS users in this (HIGHLY IMPROBABLE) case but that is not our fault var originalHash = user.PasswordHash; - var isDbUser = originalHash != null; - bool usingSystemIdentity = systemIdentity != null && !isDbUser; + var isLikelyDbUser = originalHash != null; + bool usingSystemIdentity = systemIdentity != null && !isLikelyDbUser; if (!oAuthLogin) if (!usingSystemIdentity) { // DB User password check and update - if (originalHash == null || !cryptographySuite.CheckUserPassword(user, ApiHeaders.Password)) + if (!isLikelyDbUser || !cryptographySuite.CheckUserPassword(user, ApiHeaders.Password)) return Unauthorized(); if (user.PasswordHash != originalHash) { @@ -335,14 +336,30 @@ namespace Tgstation.Server.Host.Controllers await DatabaseContext.Save(cancellationToken); } } - else if (systemIdentity.Username != user.Name) + else { - // System identity username change update - Logger.LogDebug("User ID {userId}'s system identity needs a refresh, updating database.", user.Id); - DatabaseContext.Users.Attach(user); - user.Name = systemIdentity.Username; - user.CanonicalName = Models.User.CanonicalizeName(user.Name); - await DatabaseContext.Save(cancellationToken); + var usernameMismatch = systemIdentity.Username != user.Name; + if (isLikelyDbUser || usernameMismatch) + { + DatabaseContext.Users.Attach(user); + if (isLikelyDbUser) + { + // cleanup from https://github.com/tgstation/tgstation-server/issues/1528 + Logger.LogDebug("System user ID {userId}'s PasswordHash is polluted, updating database.", user.Id); + user.PasswordHash = null; + user.LastPasswordUpdate = DateTimeOffset.UtcNow; + } + + if (usernameMismatch) + { + // System identity username change update + Logger.LogDebug("User ID {userId}'s system identity needs a refresh, updating database.", user.Id); + user.Name = systemIdentity.Username; + user.CanonicalName = Models.User.CanonicalizeName(user.Name); + } + + await DatabaseContext.Save(cancellationToken); + } } // Now that the bookeeping is done, tell them to fuck off if necessary diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs index 60be70f7d2..2af7714f42 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs @@ -182,8 +182,7 @@ namespace Tgstation.Server.Host.Controllers if (earlyOut != null && !newCancellationToken.IsCancellationRequested) cts.Cancel(); }, - newCancellationToken) - ; + newCancellationToken); } catch (OperationCanceledException) { @@ -419,8 +418,7 @@ namespace Tgstation.Server.Host.Controllers .ChatBots .AsQueryable() .Where(x => x.InstanceId == originalModel.Id) - .CountAsync(cancellationToken) - ; + .CountAsync(cancellationToken); if (countOfExistingChatBots > model.ChatBotLimit.Value) return Conflict(new ErrorMessageResponse(ErrorCode.ChatBotMax)); @@ -486,8 +484,7 @@ namespace Tgstation.Server.Host.Controllers job, (core, databaseContextFactory, paramJob, progressHandler, ct) // core will be null here since the instance is offline => InstanceOperations.MoveInstance(originalModel, originalModelPath, ct), - cancellationToken) - ; + cancellationToken); api.MoveJob = job.ToApi(); } @@ -548,8 +545,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix)) .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy) .Include(x => x.Instance) - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); var needsUpdate = false; var result = await Paginated( @@ -565,8 +561,7 @@ namespace Tgstation.Server.Host.Controllers }, page, pageSize, - cancellationToken) - ; + cancellationToken); if (needsUpdate) await DatabaseContext.Save(cancellationToken); @@ -625,8 +620,7 @@ namespace Tgstation.Server.Host.Controllers .SelectMany(x => x.Jobs) .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix)) .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); api.MoveJob = moveJob?.ToApi(); await CheckAccessible(api, cancellationToken); return Json(api); @@ -654,14 +648,12 @@ namespace Tgstation.Server.Host.Controllers var usersInstancePermissionSet = await BaseQuery() .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == AuthenticationContext.PermissionSet.Id.Value) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (usersInstancePermissionSet == default) { // does the instance actually exist? var instanceExists = await BaseQuery() - .AnyAsync(cancellationToken) - ; + .AnyAsync(cancellationToken); if (!instanceExists) return Gone(); @@ -700,8 +692,7 @@ namespace Tgstation.Server.Host.Controllers .GetAvailablePort( Math.Min((ushort)(ddPort.Value + 1), DefaultApiValidationPort), false, - cancellationToken) - ; + cancellationToken); if (!dmPort.HasValue) return null; diff --git a/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs b/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs index c04d169e3d..9caea8b34f 100644 --- a/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstancePermissionSetController.cs @@ -73,8 +73,7 @@ namespace Tgstation.Server.Host.Controllers { UserId = x.UserId, }) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (existingPermissionSet == default) return Gone(); @@ -86,8 +85,7 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .Where(x => x.Id == existingPermissionSet.UserId.Value) .Select(x => x.CanonicalName) - .FirstAsync(cancellationToken) - ; + .FirstAsync(cancellationToken); if (userCanonicalName == Models.User.CanonicalizeName(Models.User.TgsSystemUserName)) return Forbid(); @@ -137,8 +135,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == model.PermissionSetId) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (originalPermissionSet == null) return Gone(); @@ -219,8 +216,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (permissionSet == default) return Gone(); return Json(permissionSet.ToApi()); @@ -246,8 +242,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == Instance.Id) .SelectMany(x => x.InstancePermissionSets) .Where(x => x.PermissionSetId == id) - .DeleteAsync(cancellationToken) - ; + .DeleteAsync(cancellationToken); return numDeleted > 0 ? NoContent() : Gone(); } } diff --git a/src/Tgstation.Server.Host/Controllers/JobController.cs b/src/Tgstation.Server.Host/Controllers/JobController.cs index 577c3113bb..e361562e9e 100644 --- a/src/Tgstation.Server.Host/Controllers/JobController.cs +++ b/src/Tgstation.Server.Host/Controllers/JobController.cs @@ -127,8 +127,7 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .Include(x => x.StartedBy) .Where(x => x.Id == id && x.Instance.Id == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (job == default) return NotFound(); @@ -162,8 +161,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == id && x.Instance.Id == Instance.Id) .Include(x => x.StartedBy) .Include(x => x.CancelledBy) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (job == default) return NotFound(); var api = job.ToApi(); diff --git a/src/Tgstation.Server.Host/Controllers/LimitedFileStreamResultExecutor.cs b/src/Tgstation.Server.Host/Controllers/LimitedFileStreamResultExecutor.cs index d26b0e355a..8af60dcb06 100644 --- a/src/Tgstation.Server.Host/Controllers/LimitedFileStreamResultExecutor.cs +++ b/src/Tgstation.Server.Host/Controllers/LimitedFileStreamResultExecutor.cs @@ -50,8 +50,7 @@ namespace Tgstation.Server.Host.Controllers outputStream, contentLength, BufferSize, - cancellationToken) - ; + cancellationToken); } else { @@ -61,8 +60,7 @@ namespace Tgstation.Server.Host.Controllers outputStream, rangeLength, BufferSize, - cancellationToken) - ; + cancellationToken); } } catch (OperationCanceledException) diff --git a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs index 269165b4fd..10d671a134 100644 --- a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs +++ b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs @@ -103,8 +103,7 @@ namespace Tgstation.Server.Host.Controllers .RepositorySettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentModel == default) return Gone(); @@ -178,19 +177,16 @@ namespace Tgstation.Server.Host.Controllers databaseContext.Instances.Attach(instance); if (await PopulateApi(api, repos, databaseContext, instance, ct)) await databaseContext.Save(ct); - }) - ; + }); }, - cancellationToken) - ; + cancellationToken); api.Origin = model.Origin; api.Reference = model.Reference; api.ActiveJob = job.ToApi(); return Created(api); - }) - ; + }); } /// @@ -210,8 +206,7 @@ namespace Tgstation.Server.Host.Controllers .RepositorySettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentModel == default) return Gone(); @@ -233,8 +228,7 @@ namespace Tgstation.Server.Host.Controllers await jobManager.RegisterOperation( job, (core, databaseContextFactory, paramJob, progressReporter, ct) => core.RepositoryManager.DeleteRepository(ct), - cancellationToken) - ; + cancellationToken); api.ActiveJob = job.ToApi(); return Accepted(api); } @@ -258,8 +252,7 @@ namespace Tgstation.Server.Host.Controllers .RepositorySettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentModel == default) return Gone(); @@ -286,8 +279,7 @@ namespace Tgstation.Server.Host.Controllers } return Json(api); - }) - ; + }); } /// @@ -347,8 +339,7 @@ namespace Tgstation.Server.Host.Controllers .RepositorySettings .AsQueryable() .Where(x => x.InstanceId == Instance.Id) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentModel == default) return Gone(); @@ -412,8 +403,7 @@ namespace Tgstation.Server.Host.Controllers await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken); return null; - }) - ; + }); if (earlyOut != null) return earlyOut; diff --git a/src/Tgstation.Server.Host/Controllers/UserController.cs b/src/Tgstation.Server.Host/Controllers/UserController.cs index 78ed4839c7..6b4dee0594 100644 --- a/src/Tgstation.Server.Host/Controllers/UserController.cs +++ b/src/Tgstation.Server.Host/Controllers/UserController.cs @@ -127,9 +127,9 @@ namespace Tgstation.Server.Host.Controllers dbUser.Name = sysIdentity.Username; dbUser.SystemIdentifier = sysIdentity.Uid; } - catch (NotImplementedException) + catch (NotImplementedException ex) { - return RequiresPosixSystemIdentity(); + return RequiresPosixSystemIdentity(ex); } else if (!(model.Password?.Length == 0 && model.OAuthConnections?.Any() == true)) { @@ -144,7 +144,7 @@ namespace Tgstation.Server.Host.Controllers await DatabaseContext.Save(cancellationToken); - Logger.LogInformation("Created new user {0} ({1})", dbUser.Name, dbUser.Id); + Logger.LogInformation("Created new user {name} ({id})", dbUser.Name, dbUser.Id); return Created(dbUser.ToApi()); } @@ -195,8 +195,7 @@ namespace Tgstation.Server.Host.Controllers .Include(x => x.Group) .ThenInclude(x => x.PermissionSet) .Include(x => x.PermissionSet) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (originalUser == default) return NotFound(); @@ -215,12 +214,21 @@ namespace Tgstation.Server.Host.Controllers || (!oAuthEdit && model.OAuthConnections != null)) return Forbid(); + var originalUserHasSid = originalUser.SystemIdentifier != null; + if (originalUserHasSid && originalUser.PasswordHash != null) + { + // cleanup from https://github.com/tgstation/tgstation-server/issues/1528 + Logger.LogDebug("System user ID {userId}'s PasswordHash is polluted, updating database.", originalUser.Id); + originalUser.PasswordHash = null; + originalUser.LastPasswordUpdate = DateTimeOffset.UtcNow; + } + if (model.SystemIdentifier != null && model.SystemIdentifier != originalUser.SystemIdentifier) return BadRequest(new ErrorMessageResponse(ErrorCode.UserSidChange)); if (model.Password != null) { - if (model.SystemIdentifier != null) + if (originalUserHasSid) return BadRequest(new ErrorMessageResponse(ErrorCode.UserMismatchPasswordSid)); var result = TrySetPassword(originalUser, model.Password, false); @@ -265,8 +273,7 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .Where(x => x.Id == model.Group.Id) .Include(x => x.PermissionSet) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (originalUser.Group == default) return Gone(); @@ -408,8 +415,7 @@ namespace Tgstation.Server.Host.Controllers .AsQueryable() .Where(x => x.Id == model.Group.Id) .Include(x => x.PermissionSet) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); else permissionSet = new Models.PermissionSet { diff --git a/src/Tgstation.Server.Host/Controllers/UserGroupController.cs b/src/Tgstation.Server.Host/Controllers/UserGroupController.cs index 1e38468534..a7269ebaf4 100644 --- a/src/Tgstation.Server.Host/Controllers/UserGroupController.cs +++ b/src/Tgstation.Server.Host/Controllers/UserGroupController.cs @@ -75,8 +75,7 @@ namespace Tgstation.Server.Host.Controllers var totalGroups = await DatabaseContext .Groups .AsQueryable() - .CountAsync(cancellationToken) - ; + .CountAsync(cancellationToken); if (totalGroups >= generalConfiguration.UserGroupLimit) return Conflict(new ErrorMessageResponse(ErrorCode.UserGroupLimitReached)); @@ -121,8 +120,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == model.Id) .Include(x => x.PermissionSet) .Include(x => x.Users) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (currentGroup == default) return Gone(); @@ -167,8 +165,7 @@ namespace Tgstation.Server.Host.Controllers .Where(x => x.Id == id) .Include(x => x.Users) .Include(x => x.PermissionSet) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (group == default) return Gone(); return Json(group.ToApi(true)); @@ -220,8 +217,7 @@ namespace Tgstation.Server.Host.Controllers .Groups .AsQueryable() .Where(x => x.Id == id && x.Users.Count == 0) - .DeleteAsync(cancellationToken) - ; + .DeleteAsync(cancellationToken); if (numDeleted > 0) return NoContent(); @@ -231,8 +227,7 @@ namespace Tgstation.Server.Host.Controllers .Groups .AsQueryable() .Where(x => x.Id == id) - .AnyAsync(cancellationToken) - ; + .AnyAsync(cancellationToken); return groupExists ? Conflict(new ErrorMessageResponse(ErrorCode.UserGroupNotEmpty)) diff --git a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs index b0dd4eb436..66e74968e0 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs @@ -215,8 +215,7 @@ namespace Tgstation.Server.Host.Database .Users .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(User.TgsSystemUserName)) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (tgsUser != null) logger.LogError( @@ -233,8 +232,7 @@ namespace Tgstation.Server.Host.Database var allInstances = await databaseContext .Instances .AsQueryable() - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); foreach (var instance in allInstances) instance.Path = instance.Path.Replace('\\', '/'); } @@ -246,8 +244,7 @@ namespace Tgstation.Server.Host.Database .AsQueryable() .Where(x => x.TopicRequestTimeout == 0) .Select(x => x.Id) - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); var rowsUpdated = ids.Count; foreach (var id in ids) @@ -318,8 +315,7 @@ namespace Tgstation.Server.Host.Database .Include(x => x.CreatedBy) .Include(x => x.PermissionSet) .Include(x => x.Group) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (admin == default) SeedAdminUser(databaseContext); diff --git a/src/Tgstation.Server.Host/Jobs/JobService.cs b/src/Tgstation.Server.Host/Jobs/JobService.cs index 971150061a..efa0b09137 100644 --- a/src/Tgstation.Server.Host/Jobs/JobService.cs +++ b/src/Tgstation.Server.Host/Jobs/JobService.cs @@ -108,8 +108,7 @@ namespace Tgstation.Server.Host.Jobs if (job.StartedBy == null) job.StartedBy = await databaseContext .Users - .GetTgsUser(cancellationToken) - ; + .GetTgsUser(cancellationToken); else job.StartedBy = new User { diff --git a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs index c28d1e1da1..24ab9707ea 100644 --- a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs +++ b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs @@ -76,8 +76,7 @@ namespace Tgstation.Server.Host.Security .Include(x => x.Group) .ThenInclude(x => x.PermissionSet) .Include(x => x.OAuthConnections) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (user == default) { logger.LogWarning("Unable to find user with ID {0}!", userId); @@ -110,8 +109,7 @@ namespace Tgstation.Server.Host.Security .AsQueryable() .Where(x => x.PermissionSetId == userPermissionSet.Id && x.InstanceId == instanceId && x.Instance.SwarmIdentifer == swarmConfiguration.Identifier) .Include(x => x.Instance) - .FirstOrDefaultAsync(cancellationToken) - ; + .FirstOrDefaultAsync(cancellationToken); if (instancePermissionSet == null) logger.LogDebug("User {0} does not have permissions on instance {1}!", userId, instanceId.Value); diff --git a/src/Tgstation.Server.Host/Security/ClaimsInjector.cs b/src/Tgstation.Server.Host/Security/ClaimsInjector.cs index 933e073ec0..de5dacc66e 100644 --- a/src/Tgstation.Server.Host/Security/ClaimsInjector.cs +++ b/src/Tgstation.Server.Host/Security/ClaimsInjector.cs @@ -68,8 +68,7 @@ namespace Tgstation.Server.Host.Security userId, apiHeaders.InstanceId, tokenValidatedContext.SecurityToken.ValidFrom, - cancellationToken) - ; + cancellationToken); var authenticationContext = authenticationContextFactory.CurrentAuthenticationContext; diff --git a/src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs b/src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs index 3646d71cd1..47ec0f3e3d 100644 --- a/src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs +++ b/src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs @@ -63,11 +63,15 @@ namespace Tgstation.Server.Host.Security PrincipalContext pc = null; UserPrincipal principal = null; + GetUserAndDomainName(user.SystemIdentifier, out _, out var domainName); + bool TryGetPrincipalFromContextType(ContextType contextType) { try { - pc = new PrincipalContext(contextType); + pc = domainName != null + ? new PrincipalContext(contextType, domainName) + : new PrincipalContext(contextType); cancellationToken.ThrowIfCancellationRequested(); principal = UserPrincipal.FindByIdentity(pc, user.SystemIdentifier); } @@ -75,9 +79,13 @@ namespace Tgstation.Server.Host.Security { throw; } - catch (Exception e) + catch (Exception ex) { - logger.LogWarning(e, "Error loading user for context type {0}!", contextType); + logger.LogDebug( + ex, + "Error loading user for context type {contextType} and principal \"{domainName}\"!", + contextType, + domainName); } finally { diff --git a/src/Tgstation.Server.Host/Setup/SetupWizard.cs b/src/Tgstation.Server.Host/Setup/SetupWizard.cs index 629dbf0a41..c4633f0846 100644 --- a/src/Tgstation.Server.Host/Setup/SetupWizard.cs +++ b/src/Tgstation.Server.Host/Setup/SetupWizard.cs @@ -176,8 +176,7 @@ namespace Tgstation.Server.Host.Setup await console.WriteAsync( $"API Port (leave blank for default of {GeneralConfiguration.DefaultApiPort}): ", false, - cancellationToken) - ; + cancellationToken); var portString = await console.ReadLineAsync(false, cancellationToken); if (String.IsNullOrWhiteSpace(portString)) return null; @@ -319,8 +318,7 @@ namespace Tgstation.Server.Host.Setup await console.WriteAsync(resolvedPath, true, cancellationToken); bool writeResolved = await PromptYesNo( "Would you like to save the relative path in the configuration? If not, the full path will be saved. (y/n): ", - cancellationToken) - ; + cancellationToken); if (writeResolved) databaseName = resolvedPath; @@ -344,23 +342,19 @@ namespace Tgstation.Server.Host.Setup await console.WriteAsync( "NOTE: It is HIGHLY reccommended that TGS runs on a complete relational database, specfically *NOT* Sqlite.", true, - cancellationToken) - ; + cancellationToken); await console.WriteAsync( "Sqlite, by nature cannot perform several DDL operations. Because of this future compatiblility cannot be guaranteed.", true, - cancellationToken) - ; + cancellationToken); await console.WriteAsync( "This means that you may not be able to update to the next minor version of TGS without a clean re-installation!", true, - cancellationToken) - ; + cancellationToken); await console.WriteAsync( "Please consider taking the time to set up a relational database if this is meant to be a long-standing server.", true, - cancellationToken) - ; + cancellationToken); await console.WriteAsync(String.Empty, true, cancellationToken); await asyncDelayer.Delay(TimeSpan.FromSeconds(3), cancellationToken); @@ -379,8 +373,7 @@ namespace Tgstation.Server.Host.Setup DatabaseType.SqlServer, DatabaseType.Sqlite), false, - cancellationToken) - ; + cancellationToken); var databaseTypeString = await console.ReadLineAsync(false, cancellationToken); if (Enum.TryParse(databaseTypeString, out var databaseType)) return databaseType; @@ -1007,8 +1000,7 @@ namespace Tgstation.Server.Host.Setup elasticSearchConfiguration, controlPanelConfiguration, swarmConfiguration, - cancellationToken) - ; + cancellationToken); } /// diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs index 8f8a5ce7a9..14bb870554 100644 --- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs +++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs @@ -965,8 +965,7 @@ namespace Tgstation.Server.Host.Swarm await Task.WhenAll( currentSwarmServers .Where(x => !x.Controller) - .Select(HealthRequestForServer)) - ; + .Select(HealthRequestForServer)); lock (swarmServers) if (swarmServers.Count != currentSwarmServers.Count) diff --git a/src/Tgstation.Server.Host/Utils/PortAllocator.cs b/src/Tgstation.Server.Host/Utils/PortAllocator.cs index 87ac3ecd05..9b125103d0 100644 --- a/src/Tgstation.Server.Host/Utils/PortAllocator.cs +++ b/src/Tgstation.Server.Host/Utils/PortAllocator.cs @@ -67,16 +67,14 @@ namespace Tgstation.Server.Host.Utils .AsQueryable() .Where(x => x.Instance.SwarmIdentifer == swarmConfiguration.Identifier) .Select(x => x.Port) - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); var dmPorts = await databaseContext .DreamMakerSettings .AsQueryable() .Where(x => x.Instance.SwarmIdentifer == swarmConfiguration.Identifier) .Select(x => x.ApiValidationPort) - .ToListAsync(cancellationToken) - ; + .ToListAsync(cancellationToken); var exceptions = new List(); ushort port = 0; diff --git a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs index 146b9f24ba..766451ab97 100644 --- a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs +++ b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs @@ -224,35 +224,45 @@ namespace Tgstation.Server.Tests.Live.Instance Assert.AreEqual(1, dumpFiles.Length); File.Delete(dumpFiles.Single()); - KillDD(true); - var jobTcs = new TaskCompletionSource(); - var killTaskStarted = new TaskCompletionSource(); - var killTask = Task.Run(() => - { - killTaskStarted.SetResult(); - while (!jobTcs.Task.IsCompleted) - KillDD(false); - }, cancellationToken); - JobResponse job; - try + while (true) { - await killTaskStarted.Task; - var dumpTask = instanceClient.DreamDaemon.CreateDump(cancellationToken); - job = await WaitForJob(await dumpTask, 20, true, null, cancellationToken); - } - finally - { - jobTcs.SetResult(); - await killTask; + KillDD(true); + var jobTcs = new TaskCompletionSource(); + var killTaskStarted = new TaskCompletionSource(); + var killTask = Task.Run(() => + { + killTaskStarted.SetResult(); + while (!jobTcs.Task.IsCompleted) + KillDD(false); + }, cancellationToken); + + try + { + await killTaskStarted.Task; + var dumpTask = instanceClient.DreamDaemon.CreateDump(cancellationToken); + job = await WaitForJob(await dumpTask, 20, true, null, cancellationToken); + } + finally + { + jobTcs.SetResult(); + await killTask; + } + + // these can also happen + + if (!(new PlatformIdentifier().IsWindows + && (job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_ACCESSDENIED: Access is denied.") + || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_HANDLE: The handle is invalid.") + || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: 3489660936: Unknown error (0xd0000008)") + || job.ExceptionDetails.Contains("System.InvalidOperationException: No process is associated with this object.")))) + break; + + var restartJob = await instanceClient.DreamDaemon.Restart(cancellationToken); + await WaitForJob(restartJob, 20, false, null, cancellationToken); } - // these can also happen - if (!(new PlatformIdentifier().IsWindows - && (job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_ACCESSDENIED: Access is denied.") - || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: E_HANDLE: The handle is invalid.") - || job.ExceptionDetails.Contains("BetterWin32Errors.Win32Exception: 3489660936: Unknown error (0xd0000008)")))) // kek - Assert.IsTrue(job.ErrorCode == ErrorCode.DreamDaemonOffline || job.ErrorCode == ErrorCode.GCoreFailure, $"{job.ErrorCode}: {job.ExceptionDetails}"); + Assert.IsTrue(job.ErrorCode == ErrorCode.DreamDaemonOffline || job.ErrorCode == ErrorCode.GCoreFailure, $"{job.ErrorCode}: {job.ExceptionDetails}"); await Task.Delay(TimeSpan.FromSeconds(20), cancellationToken);