mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-26 22:48:20 +01:00
Merge pull request #1954 from tgstation/GraphQLGitHub [RESTDeploy][GQLDeploy]
Initial GraphQL API release. Also releasing REST API v10.10
This commit is contained in:
@@ -191,7 +191,7 @@ This prevents nesting levels from getting deeper then they need to be.
|
||||
|
||||
- Some terminology to help understand the architecture:
|
||||
- An instance can be thought of as a separate server. It has a separate directory, repository, set of byond installations, etc... The only thing shared amongst instances is API surface, users, global configuration, the active tgstation-server version, and the host machine.
|
||||
- API refers to the HTTP API unless otherwise specified.
|
||||
- API refers to the REST API unless otherwise specified.
|
||||
- The entirety of server functionality resides in the host (Tgstation.Server.Host) project.
|
||||
- A Component is a service running in tgstation-server to help with instance functionality. These can only be communicated with via the HTTP or DM APIs.
|
||||
- There is a difference between Watchdog and Host Watchdog. The former monitors DreamDaemon uptime, the latter handles updating tgstation-server.
|
||||
@@ -247,7 +247,7 @@ Warning: You may need to temporarily set valid MySql credentials in [MySqlDesign
|
||||
|
||||
OAuth providers are hardcoded but it is fairly easy to add new ones. The flow doesn't need to be strict OAuth either (r.e. /tg/ forums). Follow the following steps:
|
||||
|
||||
1. Add the name to the [Tgstation.Server.Api.Models.OAuthProviders](../src/Tgstation.Server.Api/Models/OAuthProviders.cs) enum (Also necessitates a minor HTTP API version bump).
|
||||
1. Add the name to the [Tgstation.Server.Api.Models.OAuthProviders](../src/Tgstation.Server.Api/Models/OAuthProviders.cs) enum (Also necessitates a minor API version bump to the HTTP APIs (REST/GraphQL)).
|
||||
1. Create an implementation of [IOAuthValidator](../src/Tgstation.Server.Host/Security/OAuth/IOAuthValidator.cs).
|
||||
- Most providers can simply override the [GenericOAuthValidator](../src/Tgstation.Server.Host/Security/OAuth/GenericOAuthValidator.cs).
|
||||
1. Construct the implementation in the [OAuthProviders](../src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs) class.
|
||||
@@ -275,7 +275,8 @@ Major changes should be committed to the `VX` branch created when the time for a
|
||||
|
||||
We have several subcomponent APIs we ship with the core server that have their own versions.
|
||||
|
||||
- HTTP API
|
||||
- REST API
|
||||
- GraphQL API
|
||||
- DreamMaker API
|
||||
- Interop API
|
||||
- Configuration File
|
||||
@@ -308,7 +309,7 @@ Word commit names descriptively. Only submit work through pull requests (With th
|
||||
|
||||
At the time of this writing, the repository is configured to automate much of the deployment/release process.
|
||||
|
||||
When the new API, client, or DMAPI is ready to be released, update the `Version.props` file appropriately and merge the pull request with the text `[APIDeploy]`, `[NuGetDeploy]`, or `[DMDeploy]` respectively in the commit message (or all three!). The release will be published automatically.
|
||||
When the new API, client, or DMAPI is ready to be released, update the `Version.props` file appropriately and merge the pull request with the text `[RESTDeploy]`, `[GQLDeploy]`, `[NugetDeploy]`, or `[DMDeploy]` respectively in the commit message (or all three!). The release will be published automatically.
|
||||
|
||||
That step should be taken for the latest API and client before releasing the core version that uses them if applicable.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ They will be amalgamated together in the end.
|
||||
Categories are used by [the release notes tool](../tools/Tgstation.Server.ReleaseNotes) to generate formatted changelists used in releases.
|
||||
The default category is Core.
|
||||
Only one category may be specified for a 🆑 block.
|
||||
Valid categories are Core, DreamMaker API, HTTP API, Host Watchdog, Web Control Panel, Configuration, Nuget: Api, Nuget: Client, and Nuget: Common.
|
||||
Valid categories are Core, DreamMaker API, REST API, GraphQL API, Host Watchdog, Web Control Panel, Configuration, Nuget: Api, Nuget: Client, and Nuget: Common.
|
||||
/🆑
|
||||
|
||||
[Why]: # (If this does not close or work on an existing GitHub issue, please add a short description [two lines down] of why you think these changes would benefit the server. If you can't justify it in words, it might not be worth adding.)
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
# - Checks commit tags for deployment intents
|
||||
# - Deploys DreamMaker API zip [DMDeploy] (dev/master)
|
||||
# - Deploys Nuget Packages [NugetDeploy] (dev/master)
|
||||
# - Deploys HTTP API swagger.json [APIDeploy] (dev/master)
|
||||
# - Deploys HTTP API swagger.json [RESTDeploy] (dev/master)
|
||||
# - Deploys GraphQL API schema.graphql [GQLDeploy] (dev/master)
|
||||
# - Deploys tgstation-server [TGSDeploy] (master)
|
||||
# - GitHub Releases: https://github.com/tgstation/tgstation-server/releases
|
||||
# - Docker: https://hub.docker.com/r/tgstation/server
|
||||
@@ -741,6 +742,13 @@ jobs:
|
||||
name: openapi-spec
|
||||
path: C:/tgs_api.json
|
||||
|
||||
- name: Store GraphQL Schema
|
||||
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Advanced' && matrix.database-type == 'SqlServer' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: graphql-schema
|
||||
path: ./artifacts/tgs-api.graphql
|
||||
|
||||
- name: Package Server Service
|
||||
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' && matrix.database-type == 'PostgresSql' }}
|
||||
run: |
|
||||
@@ -1611,11 +1619,11 @@ jobs:
|
||||
- name: GitHub Requires at Least One Step for a Job
|
||||
run: exit 0
|
||||
|
||||
deploy-http:
|
||||
name: Deploy HTTP API
|
||||
deploy-rest:
|
||||
name: Deploy REST API
|
||||
needs: deployment-gate
|
||||
runs-on: windows-latest
|
||||
if: contains(github.event.head_commit.message, '[APIDeploy]')
|
||||
if: contains(github.event.head_commit.message, '[RESTDeploy]')
|
||||
steps:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -1630,7 +1638,7 @@ jobs:
|
||||
shell: powershell
|
||||
run: |
|
||||
[XML]$versionXML = Get-Content build/Version.props
|
||||
$apiVersion = $versionXML.Project.PropertyGroup.TgsApiVersion
|
||||
$apiVersion = $versionXML.Project.PropertyGroup.TgsRestVersion
|
||||
echo "TGS_API_VERSION=$apiVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
|
||||
- name: Retrieve OpenAPI Spec
|
||||
@@ -1661,7 +1669,7 @@ jobs:
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
TGS_RELEASE_NOTES_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
run: dotnet release_notes_bins/Tgstation.Server.ReleaseNotes.dll ${{ env.TGS_API_VERSION }} --httpapi
|
||||
run: dotnet release_notes_bins/Tgstation.Server.ReleaseNotes.dll ${{ env.TGS_API_VERSION }} --restapi
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: actions/create-release@v1
|
||||
@@ -1670,7 +1678,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
with:
|
||||
tag_name: api-v${{ env.TGS_API_VERSION }}
|
||||
release_name: tgstation-server API v${{ env.TGS_API_VERSION }}
|
||||
release_name: tgstation-server REST API v${{ env.TGS_API_VERSION }}
|
||||
body_path: release_notes.md
|
||||
commitish: ${{ github.event.head_commit.id }}
|
||||
|
||||
@@ -1684,6 +1692,86 @@ jobs:
|
||||
asset_name: swagger.json
|
||||
asset_content_type: application/json
|
||||
|
||||
deploy-gql:
|
||||
name: Deploy GraphQL API
|
||||
needs: deployment-gate
|
||||
runs-on: windows-latest
|
||||
if: contains(github.event.head_commit.message, '[GQLDeploy]')
|
||||
steps:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.TGS_DOTNET_VERSION }}.0.x
|
||||
dotnet-quality: ${{ env.TGS_DOTNET_QUALITY }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Parse API version
|
||||
shell: powershell
|
||||
run: |
|
||||
[XML]$versionXML = Get-Content build/Version.props
|
||||
$apiVersion = $versionXML.Project.PropertyGroup.TgsGraphQLVersion
|
||||
echo "TGS_API_VERSION=$apiVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
[Version]$parsedVersion = $apiVersion
|
||||
if ($parsedVersion.Major -eq 0) {
|
||||
echo "TGS_GRAPHQL_PRERELEASE=true" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
} else {
|
||||
echo "TGS_GRAPHQL_PRERELEASE=false" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||
}
|
||||
|
||||
- name: Retrieve GraphQL Schema
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: graphql-schema
|
||||
path: schema
|
||||
|
||||
- name: Grab Most Recent Changelog
|
||||
shell: powershell
|
||||
run: |
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
Invoke-WebRequest -Uri https://raw.githubusercontent.com/tgstation/tgstation-server/gh-pages/changelog.yml -OutFile changelog.yml
|
||||
|
||||
- name: Retrieve ReleaseNotes Binaries
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release_notes_bins
|
||||
path: release_notes_bins
|
||||
|
||||
- name: Generate App Token
|
||||
id: app-token-generation
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
TGS_RELEASE_NOTES_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
run: dotnet release_notes_bins/Tgstation.Server.ReleaseNotes.dll ${{ env.TGS_API_VERSION }} --graphqlapi
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: actions/create-release@v1
|
||||
id: create_release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
with:
|
||||
tag_name: graphql-v${{ env.TGS_API_VERSION }}
|
||||
release_name: tgstation-server GraphQL API v${{ env.TGS_API_VERSION }}
|
||||
body_path: release_notes.md
|
||||
commitish: ${{ github.event.head_commit.id }}
|
||||
prerelease: ${{ env.TGS_GRAPHQL_PRERELEASE }}
|
||||
|
||||
- name: Upload GraphQL Schema
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./schema/tgs-api.graphql
|
||||
asset_name: tgs-api.graphql
|
||||
asset_content_type: text/plain
|
||||
|
||||
deploy-dm:
|
||||
name: Deploy DreamMaker API
|
||||
needs: deployment-gate
|
||||
@@ -1818,7 +1906,7 @@ jobs:
|
||||
|
||||
ensure-release:
|
||||
name: Ensure TGS Release is Latest GitHub Release
|
||||
needs: [deploy-dm, deploy-http]
|
||||
needs: [deploy-dm, deploy-rest, deploy-gql]
|
||||
runs-on: ubuntu-latest
|
||||
if: (!(cancelled() || failure())) && (!contains(github.event.head_commit.message, '[TGSDeploy]')) && (needs.deploy-dm.result == 'success' || needs.deploy-http.result == 'success')
|
||||
steps:
|
||||
@@ -1848,7 +1936,7 @@ jobs:
|
||||
|
||||
deploy-tgs:
|
||||
name: Deploy TGS
|
||||
needs: [deploy-dm, deploy-http, deployment-gate]
|
||||
needs: [deploy-dm, deploy-rest, deploy-gql, deployment-gate]
|
||||
runs-on: windows-latest
|
||||
if: (!(cancelled() || failure())) && github.event.ref == 'refs/heads/master' && contains(github.event.head_commit.message, '[TGSDeploy]') && needs.deployment-gate.result == 'success'
|
||||
env:
|
||||
@@ -1940,6 +2028,12 @@ jobs:
|
||||
name: openapi-spec
|
||||
path: swagger
|
||||
|
||||
- name: Retrieve GraphQL Schema
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: graphql-schema
|
||||
path: schema
|
||||
|
||||
- name: Retrieve Debian Packaging Archive
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -2035,7 +2129,7 @@ jobs:
|
||||
asset_name: DMAPI.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Upload OpenApi Spec Artifact
|
||||
- name: Upload REST API Artifact
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
@@ -2045,6 +2139,16 @@ jobs:
|
||||
asset_name: swagger.json
|
||||
asset_content_type: application/json
|
||||
|
||||
- name: Upload GraphQL API Artifact
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token-generation.outputs.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./schema/tgs-api.graphql
|
||||
asset_name: tgs-api.graphql
|
||||
asset_content_type: text/plain
|
||||
|
||||
- name: Upload Server Update Package Artifact
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
|
||||
+2
-1
@@ -5,7 +5,8 @@
|
||||
<PropertyGroup>
|
||||
<TgsCoreVersion>6.10.0</TgsCoreVersion>
|
||||
<TgsConfigVersion>5.3.0</TgsConfigVersion>
|
||||
<TgsApiVersion>10.10.0</TgsApiVersion>
|
||||
<TgsRestVersion>10.10.0</TgsRestVersion>
|
||||
<TgsGraphQLVersion>0.1.0</TgsGraphQLVersion>
|
||||
<TgsCommonLibraryVersion>7.0.0</TgsCommonLibraryVersion>
|
||||
<TgsApiLibraryVersion>16.0.0</TgsApiLibraryVersion>
|
||||
<TgsClientVersion>19.0.0</TgsClientVersion>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ This is a series of README.md files aimed at directing people around the codebas
|
||||
- To explore the server code navigate to [Tgstation.Server.Host](./Tgstation.Server.Host).
|
||||
- To explore the DreamMaker public API navigate to [DMAPI/tgs.dm](./DMAPI/tgs.dm).
|
||||
- To explore the DMAPI internals, navigate to [DMAPI/tgs](./DMAPI/tgs).
|
||||
- To explore the HTTP API definitions navigate to [Tgstation.Server.Api](./Tgstation.Server.Api).
|
||||
- To explore the REST API definitions navigate to [Tgstation.Server.Api](./Tgstation.Server.Api).
|
||||
- To explore the C# client code navigate to [Tgstation.Server.Client](./Tgstation.Server.Client).
|
||||
|
||||
[Tgstation.Server.Host.Watchdog](./Tgstation.Server.Host.Watchdog), [Tgstation.Server.Host.Service](./Tgstation.Server.Host.Service), and [Tgstation.Server.Host.Console](./Tgstation.Server.Host.Console) are related to the Service/Console runners which have the simple task of executing Tgstation.Server.Host and updating it when requested.
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Tgstation.Server.Api
|
||||
if (requestHeaders.Headers.TryGetValue(OAuthProviderHeader, out StringValues oauthProviderValues))
|
||||
{
|
||||
var oauthProviderString = oauthProviderValues.First();
|
||||
if (Enum.TryParse<OAuthProvider>(oauthProviderString, out var oauthProvider))
|
||||
if (Enum.TryParse<OAuthProvider>(oauthProviderString, true, out var oauthProvider))
|
||||
OAuthProvider = oauthProvider;
|
||||
else
|
||||
AddError(HeaderErrorTypes.OAuthProvider, "Invalid OAuth provider!");
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<Target Name="ApplyApiVersionAttribute" BeforeTargets="CoreCompile">
|
||||
<ItemGroup>
|
||||
<AssemblyAttributes Include="Tgstation.Server.Api.Properties.ApiVersionAttribute">
|
||||
<_Parameter1>$(TgsApiVersion)</_Parameter1>
|
||||
<_Parameter1>$(TgsRestVersion)</_Parameter1>
|
||||
</AssemblyAttributes>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
query OAuthInformation {
|
||||
swarm {
|
||||
currentNode {
|
||||
gateway {
|
||||
information {
|
||||
oAuthProviderInfos {
|
||||
key
|
||||
value {
|
||||
clientId
|
||||
redirectUri
|
||||
serverUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-9
@@ -3,15 +3,7 @@ query UnauthenticatedServerInformation {
|
||||
currentNode {
|
||||
gateway {
|
||||
information {
|
||||
majorApiVersion
|
||||
oAuthProviderInfos {
|
||||
key
|
||||
value {
|
||||
clientId
|
||||
redirectUri
|
||||
serverUrl
|
||||
}
|
||||
}
|
||||
majorGraphQLApiVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TgsFrameworkVersion)</TargetFramework>
|
||||
<Version>$(TgsApiVersion)</Version>
|
||||
<!-- Opting to not version this because as far as I can tell, it'll only be used locally -->
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ namespace Tgstation.Server.Host.Authority
|
||||
ValueTask<AuthorityResponse<User>> GetId(long id, bool includeJoins, bool allowSystemUser, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="OAuthConnection"/>s for the <see cref="User"/> with a given <paramref name="userId"/>.
|
||||
/// Gets the <see cref="GraphQL.Types.OAuth.OAuthConnection"/>s for the <see cref="User"/> with a given <paramref name="userId"/>.
|
||||
/// </summary>
|
||||
/// <param name="userId">The <see cref="EntityId.Id"/> of the <see cref="User"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in an <see cref="global::System.Array"/> of <see cref="GraphQL.Types.OAuthConnection"/> <see cref="AuthorityResponse{TResult}"/>.</returns>
|
||||
ValueTask<AuthorityResponse<GraphQL.Types.OAuthConnection[]>> OAuthConnections(long userId, CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in an <see cref="global::System.Array"/> of <see cref="GraphQL.Types.OAuth.OAuthConnection"/> <see cref="AuthorityResponse{TResult}"/>.</returns>
|
||||
ValueTask<AuthorityResponse<GraphQL.Types.OAuth.OAuthConnection[]>> OAuthConnections(long userId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all registered <see cref="User"/>s.
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a <see cref="Dictionary{TKey, TValue}"/> of the requested <see cref="User"/>s.</returns>
|
||||
[DataLoader]
|
||||
public static async ValueTask<ILookup<long, GraphQL.Types.OAuthConnection>> GetOAuthConnections(
|
||||
public static async ValueTask<ILookup<long, GraphQL.Types.OAuth.OAuthConnection>> GetOAuthConnections(
|
||||
IReadOnlyList<long> userIds,
|
||||
IDatabaseContext databaseContext,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -118,7 +118,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
|
||||
return list.ToLookup(
|
||||
oauthConnection => oauthConnection.UserId,
|
||||
x => new GraphQL.Types.OAuthConnection(x.ExternalUserId!, x.Provider));
|
||||
x => new GraphQL.Types.OAuth.OAuthConnection(x.ExternalUserId!, x.Provider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -285,8 +285,8 @@ namespace Tgstation.Server.Host.Authority
|
||||
=> Queryable(includeJoins, false);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<AuthorityResponse<GraphQL.Types.OAuthConnection[]>> OAuthConnections(long userId, CancellationToken cancellationToken)
|
||||
=> new AuthorityResponse<GraphQL.Types.OAuthConnection[]>(
|
||||
public async ValueTask<AuthorityResponse<GraphQL.Types.OAuth.OAuthConnection[]>> OAuthConnections(long userId, CancellationToken cancellationToken)
|
||||
=> new AuthorityResponse<GraphQL.Types.OAuth.OAuthConnection[]>(
|
||||
await oAuthConnectionsDataLoader.LoadRequiredAsync(userId, cancellationToken));
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -57,10 +57,10 @@ using Tgstation.Server.Host.Controllers.Results;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.GraphQL;
|
||||
using Tgstation.Server.Host.GraphQL.Interceptors;
|
||||
using Tgstation.Server.Host.GraphQL.Scalars;
|
||||
using Tgstation.Server.Host.GraphQL.Subscriptions;
|
||||
using Tgstation.Server.Host.GraphQL.Types;
|
||||
using Tgstation.Server.Host.GraphQL.Types.Interceptors;
|
||||
using Tgstation.Server.Host.GraphQL.Types.Scalars;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Properties;
|
||||
|
||||
+2
-2
@@ -6,10 +6,10 @@ using System.Reflection;
|
||||
using HotChocolate.Configuration;
|
||||
using HotChocolate.Types;
|
||||
using HotChocolate.Types.Descriptors.Definitions;
|
||||
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.GraphQL.Types;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.Interceptors
|
||||
namespace Tgstation.Server.Host.GraphQL.Interceptors
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixes the names used for the default flags types in API rights.
|
||||
@@ -14,8 +14,14 @@ namespace Tgstation.Server.Host.GraphQL
|
||||
/// Root type for GraphQL mutations.
|
||||
/// </summary>
|
||||
/// <remarks>Intentionally left mostly empty, use type extensions to properly scope operations to domains.</remarks>
|
||||
[GraphQLDescription(GraphQLDescription)]
|
||||
public sealed class Mutation
|
||||
{
|
||||
/// <summary>
|
||||
/// Description to show on the <see cref="Mutation"/> type.
|
||||
/// </summary>
|
||||
public const string GraphQLDescription = "Root Mutation type";
|
||||
|
||||
/// <summary>
|
||||
/// Generate a JWT for authenticating with server. This is the only operation that accepts and required basic authentication.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using HotChocolate;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.GraphQL.Types.Scalars;
|
||||
using Tgstation.Server.Host.GraphQL.Scalars;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Mutations.Payloads
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Tgstation.Server.Host.GraphQL.Mutations
|
||||
/// <see cref="IUserGroupAuthority"/> related <see cref="Mutation"/>s.
|
||||
/// </summary>
|
||||
[ExtendObjectType(typeof(Mutation))]
|
||||
[GraphQLDescription(Mutation.GraphQLDescription)]
|
||||
public sealed class UserGroupMutations
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -13,6 +13,7 @@ using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Authority;
|
||||
using Tgstation.Server.Host.GraphQL.Mutations.Payloads;
|
||||
using Tgstation.Server.Host.GraphQL.Types;
|
||||
using Tgstation.Server.Host.GraphQL.Types.OAuth;
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
@@ -22,6 +23,7 @@ namespace Tgstation.Server.Host.GraphQL.Mutations
|
||||
/// <see cref="IUserAuthority"/> related <see cref="Mutation"/>s.
|
||||
/// </summary>
|
||||
[ExtendObjectType(typeof(Mutation))]
|
||||
[GraphQLDescription(Mutation.GraphQLDescription)]
|
||||
public sealed class UserMutations
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma warning disable CA1724 // Dumb conflict with Microsoft.EntityFrameworkCore.Query
|
||||
|
||||
using HotChocolate;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL
|
||||
{
|
||||
/// <summary>
|
||||
/// GraphQL query <see cref="global::System.Type"/>.
|
||||
/// </summary>
|
||||
[GraphQLDescription("Root Query type")]
|
||||
public sealed class Query
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
using HotChocolate.Language;
|
||||
using HotChocolate.Types;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.Scalars
|
||||
namespace Tgstation.Server.Host.GraphQL.Scalars
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ScalarType{TRuntimeType, TLiteral}"/> for encoded JSON Web Tokens.
|
||||
+1
-2
@@ -2,10 +2,9 @@
|
||||
|
||||
using HotChocolate.Language;
|
||||
using HotChocolate.Types;
|
||||
|
||||
using Tgstation.Server.Common.Extensions;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.Scalars
|
||||
namespace Tgstation.Server.Host.GraphQL.Scalars
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ScalarType{TRuntimeType, TLiteral}"/> for semantic <see cref="Version"/>s.
|
||||
@@ -16,8 +16,14 @@ namespace Tgstation.Server.Host.GraphQL
|
||||
/// Root type for GraphQL subscriptions.
|
||||
/// </summary>
|
||||
/// <remarks>Intentionally left mostly empty, use type extensions to properly scope operations to domains.</remarks>
|
||||
[GraphQLDescription(GraphQLDescription)]
|
||||
public sealed class Subscription
|
||||
{
|
||||
/// <summary>
|
||||
/// Description to show on the <see cref="Subscription"/> type.
|
||||
/// </summary>
|
||||
public const string GraphQLDescription = "Root Subscription type. Note that subscriptions are performed over Server Sent events.";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the topic name for the login session represented by a given <paramref name="authenticationContext"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Tgstation.Server.Host.GraphQL.Subscriptions
|
||||
/// Subscriptions for <see cref="User"/>.
|
||||
/// </summary>
|
||||
[ExtendObjectType(typeof(Subscription))]
|
||||
[GraphQLDescription(Subscription.GraphQLDescription)]
|
||||
public sealed class UserSubscriptions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -10,6 +10,7 @@ using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components.Interop;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.GraphQL.Types.OAuth;
|
||||
using Tgstation.Server.Host.Properties;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.Security.OAuth;
|
||||
@@ -28,7 +29,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the <see cref="GeneralConfiguration"/>.</param>
|
||||
/// <returns>A <see cref="uint"/> specifying the minimumn valid password length for TGS users.</returns>
|
||||
[TgsGraphQLAuthorize(AdministrationRights.WriteUsers | AdministrationRights.EditOwnPassword)]
|
||||
public uint? MinimumPasswordLength(
|
||||
public uint MinimumPasswordLength(
|
||||
[Service] IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(generalConfigurationOptions);
|
||||
@@ -41,7 +42,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptionsSnapshot{TOptions}"/> containing the <see cref="GeneralConfiguration"/>.</param>
|
||||
/// <returns>A <see cref="uint"/> specifying the maximum allowed attached instances for the <see cref="SwarmNode"/>.</returns>
|
||||
[TgsGraphQLAuthorize(InstanceManagerRights.Create)]
|
||||
public uint? InstanceLimit(
|
||||
public uint InstanceLimit(
|
||||
[Service] IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(generalConfigurationOptions);
|
||||
@@ -55,7 +56,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <returns>A <see cref="uint"/> specifying the maximum allowed registered users for the <see cref="ServerSwarm"/>.</returns>
|
||||
/// <remarks>This limit only applies to user creation attempts made via the current <see cref="SwarmNode"/>.</remarks>
|
||||
[TgsGraphQLAuthorize(AdministrationRights.WriteUsers)]
|
||||
public uint? UserLimit(
|
||||
public uint UserLimit(
|
||||
[Service] IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(generalConfigurationOptions);
|
||||
@@ -69,7 +70,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <returns>A <see cref="uint"/> specifying the maximum allowed registered <see cref="UserGroup"/>s for the <see cref="ServerSwarm"/>.</returns>
|
||||
/// <remarks>This limit only applies to <see cref="UserGroup"/> creation attempts made via the current <see cref="SwarmNode"/>.</remarks>
|
||||
[TgsGraphQLAuthorize(AdministrationRights.WriteUsers)]
|
||||
public uint? UserGroupLimit(
|
||||
public uint UserGroupLimit(
|
||||
[Service] IOptionsSnapshot<GeneralConfiguration> generalConfigurationOptions)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(generalConfigurationOptions);
|
||||
@@ -95,7 +96,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="platformIdentifier">The <see cref="IPlatformIdentifier"/> to use.</param>
|
||||
/// <returns><see langword="true"/> if the <see cref="SwarmNode"/> runs on a Windows operating system, <see langword="false"/> otherwise.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public bool? WindowsHost(
|
||||
public bool WindowsHost(
|
||||
[Service] IPlatformIdentifier platformIdentifier)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(platformIdentifier);
|
||||
@@ -106,7 +107,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// Gets the swarm protocol <see cref="Version"/>.
|
||||
/// </summary>
|
||||
[TgsGraphQLAuthorize]
|
||||
public Version? SwarmProtocolVersion => global::System.Version.Parse(MasterVersionsAttribute.Instance.RawSwarmProtocolVersion);
|
||||
public Version SwarmProtocolVersion => global::System.Version.Parse(MasterVersionsAttribute.Instance.RawSwarmProtocolVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="global::System.Version"/> of tgstation-server the <see cref="SwarmNode"/> is running.
|
||||
@@ -114,7 +115,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> to use.</param>
|
||||
/// <returns>The <see cref="global::System.Version"/> of tgstation-server the <see cref="SwarmNode"/> is running.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public Version? Version(
|
||||
public Version Version(
|
||||
[Service] IAssemblyInformationProvider assemblyInformationProvider)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
|
||||
@@ -122,32 +123,38 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the major HTTP API <see cref="global::System.Version"/> number of the <see cref="SwarmNode"/>.
|
||||
/// Gets the major GraphQL API <see cref="global::System.Version"/> number of the <see cref="SwarmNode"/>.
|
||||
/// </summary>
|
||||
public int MajorApiVersion => ApiHeaders.Version.Major;
|
||||
public int MajorGraphQLApiVersion => GraphQLApiVersion.Major;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HTTP API <see cref="global::System.Version"/> of the <see cref="SwarmNode"/>.
|
||||
/// Gets the GraphQL API <see cref="global::System.Version"/> of the <see cref="SwarmNode"/>.
|
||||
/// </summary>
|
||||
[TgsGraphQLAuthorize]
|
||||
public Version? ApiVersion => ApiHeaders.Version;
|
||||
public Version GraphQLApiVersion => global::System.Version.Parse(MasterVersionsAttribute.Instance.RawGraphQLVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the REST API <see cref="global::System.Version"/> of the <see cref="SwarmNode"/>.
|
||||
/// </summary>
|
||||
[TgsGraphQLAuthorize]
|
||||
public Version ApiVersion => ApiHeaders.Version;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DMAPI interop <see cref="global::System.Version"/> the <see cref="SwarmNode"/> uses.
|
||||
/// </summary>
|
||||
[TgsGraphQLAuthorize]
|
||||
public Version? DMApiVersion => DMApiConstants.InteropVersion;
|
||||
public Version DMApiVersion => DMApiConstants.InteropVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the information needed to perform open authentication with the <see cref="SwarmNode"/>.
|
||||
/// </summary>
|
||||
/// <param name="oAuthProviders">The <see cref="IOAuthProviders"/> to use.</param>
|
||||
/// <returns>A map of enabled <see cref="OAuthProvider"/>s to their <see cref="OAuthProviderInfo"/>.</returns>
|
||||
public IReadOnlyDictionary<OAuthProvider, OAuthProviderInfo> OAuthProviderInfos(
|
||||
/// <returns>A map of enabled <see cref="OAuthProvider"/>s to their <see cref="FullOAuthProviderInfo"/>.</returns>
|
||||
public OAuthProviderInfos OAuthProviderInfos(
|
||||
[Service] IOAuthProviders oAuthProviders)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(oAuthProviders);
|
||||
return oAuthProviders.ProviderInfos();
|
||||
return new OAuthProviderInfos(oAuthProviders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic OAuth provider info.
|
||||
/// </summary>
|
||||
public class BasicOAuthProviderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The client ID.
|
||||
/// </summary>
|
||||
public string ClientID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BasicOAuthProviderInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerInfo">The <see cref="OAuthProviderInfo"/> to build from.</param>
|
||||
public BasicOAuthProviderInfo(OAuthProviderInfo providerInfo)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(providerInfo);
|
||||
|
||||
ClientID = providerInfo.ClientId ?? throw new InvalidOperationException("ClientID not set!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth provider info with a <see cref="RedirectOAuthProviderInfo.RedirectUri"/> and <see cref="ServerUrl"/>.
|
||||
/// </summary>
|
||||
public sealed class FullOAuthProviderInfo : RedirectOAuthProviderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The remote service URL.
|
||||
/// </summary>
|
||||
public Uri ServerUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FullOAuthProviderInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerInfo">The <see cref="OAuthProviderInfo"/> to build from.</param>
|
||||
public FullOAuthProviderInfo(OAuthProviderInfo providerInfo)
|
||||
: base(providerInfo)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(providerInfo);
|
||||
|
||||
ServerUrl = providerInfo.ServerUrl ?? throw new InvalidOperationException("Missing OAuthProviderInfo ServerUrl!");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a valid OAuth connection.
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Security.OAuth;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of configured OAuth services.
|
||||
/// </summary>
|
||||
public sealed class OAuthProviderInfos
|
||||
{
|
||||
/// <summary>
|
||||
/// https://discord.com.
|
||||
/// </summary>
|
||||
public BasicOAuthProviderInfo? Discord { get; }
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com.
|
||||
/// </summary>
|
||||
public RedirectOAuthProviderInfo? GitHub { get; }
|
||||
|
||||
/// <summary>
|
||||
/// https://tgstation13.org.
|
||||
/// </summary>
|
||||
public RedirectOAuthProviderInfo? TGForums { get; }
|
||||
|
||||
/// <summary>
|
||||
/// https://www.keycloak.org.
|
||||
/// </summary>
|
||||
public FullOAuthProviderInfo? Keycloak { get; }
|
||||
|
||||
/// <summary>
|
||||
/// https://invisioncommunity.com.
|
||||
/// </summary>
|
||||
public FullOAuthProviderInfo? InvisionCommunity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OAuthProviderInfos"/> class.
|
||||
/// </summary>
|
||||
/// <param name="oAuthProviders">The <see cref="IOAuthProviders"/> to get data from.</param>
|
||||
public OAuthProviderInfos(IOAuthProviders oAuthProviders)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(oAuthProviders);
|
||||
|
||||
var dic = oAuthProviders.ProviderInfos();
|
||||
|
||||
TProviderInfo? TryBuild<TProviderInfo>(OAuthProvider oAuthProvider, Func<OAuthProviderInfo, TProviderInfo> contructor)
|
||||
where TProviderInfo : BasicOAuthProviderInfo
|
||||
{
|
||||
if (dic.TryGetValue(oAuthProvider, out var providerInfo))
|
||||
{
|
||||
return contructor(providerInfo);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Discord = TryBuild(OAuthProvider.Discord, info => new BasicOAuthProviderInfo(info));
|
||||
GitHub = TryBuild(OAuthProvider.GitHub, info => new RedirectOAuthProviderInfo(info));
|
||||
TGForums = TryBuild(OAuthProvider.TGForums, info => new RedirectOAuthProviderInfo(info));
|
||||
Keycloak = TryBuild(OAuthProvider.Keycloak, info => new FullOAuthProviderInfo(info));
|
||||
InvisionCommunity = TryBuild(OAuthProvider.InvisionCommunity, info => new FullOAuthProviderInfo(info));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth provider info with a <see cref="RedirectUri"/>.
|
||||
/// </summary>
|
||||
public class RedirectOAuthProviderInfo : BasicOAuthProviderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The authentication server URL.
|
||||
/// </summary>
|
||||
public Uri RedirectUri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RedirectOAuthProviderInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerInfo">The <see cref="OAuthProviderInfo"/> to build from.</param>
|
||||
public RedirectOAuthProviderInfo(OAuthProviderInfo providerInfo)
|
||||
: base(providerInfo)
|
||||
{
|
||||
RedirectUri = providerInfo!.RedirectUri ?? throw new InvalidOperationException("RedirectUri not set!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth provider info with a <see cref="ServerUrl"/>.
|
||||
/// </summary>
|
||||
public sealed class ServerUrlOAuthProviderInfo : BasicOAuthProviderInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The remote service URL.
|
||||
/// </summary>
|
||||
public Uri ServerUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerUrlOAuthProviderInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="providerInfo">The <see cref="OAuthProviderInfo"/> to build from.</param>
|
||||
public ServerUrlOAuthProviderInfo(OAuthProviderInfo providerInfo)
|
||||
: base(providerInfo)
|
||||
{
|
||||
ServerUrl = providerInfo!.ServerUrl ?? throw new InvalidOperationException("ServerUrl not set!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using HotChocolate.Types.Relay;
|
||||
|
||||
using Tgstation.Server.Host.Authority;
|
||||
using Tgstation.Server.Host.GraphQL.Interfaces;
|
||||
using Tgstation.Server.Host.GraphQL.Types.OAuth;
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Tgstation.Server.Host.Properties
|
||||
public string RawWebpanelVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Version"/> <see cref="string"/> of the control panel version built.
|
||||
/// The <see cref="Version"/> <see cref="string"/> of the host watchdog that was built alongside this TGS version.
|
||||
/// </summary>
|
||||
public string RawHostWatchdogVersion { get; }
|
||||
|
||||
@@ -42,10 +42,15 @@ namespace Tgstation.Server.Host.Properties
|
||||
public string RawMariaDBRedistVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Version"/> <see cref="string"/> of the MariaDB server bundled with TGS installs.
|
||||
/// The <see cref="Version"/> <see cref="string"/> of the TGS swarm protocol.
|
||||
/// </summary>
|
||||
public string RawSwarmProtocolVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Version"/> <see cref="string"/> of the TGS GraphQL API.
|
||||
/// </summary>
|
||||
public string RawGraphQLVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MasterVersionsAttribute"/> class.
|
||||
/// </summary>
|
||||
@@ -55,13 +60,15 @@ namespace Tgstation.Server.Host.Properties
|
||||
/// <param name="rawHostWatchdogVersion">The value of <see cref="RawHostWatchdogVersion"/>.</param>
|
||||
/// <param name="rawMariaDBRedistVersion">The value of <see cref="RawMariaDBRedistVersion"/>.</param>
|
||||
/// <param name="rawSwarmProtocolVersion">The value of <see cref="RawSwarmProtocolVersion"/>.</param>
|
||||
/// <param name="rawGraphQLVersion">The value of <see cref="RawGraphQLVersion"/>.</param>
|
||||
public MasterVersionsAttribute(
|
||||
string rawConfigurationVersion,
|
||||
string rawInteropVersion,
|
||||
string rawWebpanelVersion,
|
||||
string rawHostWatchdogVersion,
|
||||
string rawMariaDBRedistVersion,
|
||||
string rawSwarmProtocolVersion)
|
||||
string rawSwarmProtocolVersion,
|
||||
string rawGraphQLVersion)
|
||||
{
|
||||
RawConfigurationVersion = rawConfigurationVersion ?? throw new ArgumentNullException(nameof(rawConfigurationVersion));
|
||||
RawInteropVersion = rawInteropVersion ?? throw new ArgumentNullException(nameof(rawInteropVersion));
|
||||
@@ -69,6 +76,7 @@ namespace Tgstation.Server.Host.Properties
|
||||
RawHostWatchdogVersion = rawHostWatchdogVersion ?? throw new ArgumentNullException(nameof(rawHostWatchdogVersion));
|
||||
RawMariaDBRedistVersion = rawMariaDBRedistVersion ?? throw new ArgumentNullException(nameof(rawMariaDBRedistVersion));
|
||||
RawSwarmProtocolVersion = rawSwarmProtocolVersion ?? throw new ArgumentNullException(nameof(rawSwarmProtocolVersion));
|
||||
RawGraphQLVersion = rawGraphQLVersion ?? throw new ArgumentNullException(nameof(rawGraphQLVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,15 @@ Server startup can be a bit complicated so here's a walkthrough
|
||||
Here's a breakdown of things in this directory
|
||||
|
||||
- [.config](./.config) contains the dotnet-tools.json. At the time of writing, this is only used to set the version of the [dotnet ef tools](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/) used to create database migrations.
|
||||
- [Authority](./Authority) is code that contains the buisiness logic that bridges the HTTP APIs with component code and the database.
|
||||
- [ClientApp](./ClientApp) contains scripts to build and deploy the web control panel with TGS.
|
||||
- [Components](./Components) is where the bulk of the TGS implementation lives.
|
||||
- [Configuration](./Configuration) contains classes that partly make up the configuration yaml files (i.e. [appsettings.yml](./appsettings.yml)).
|
||||
- [Controllers](./Controllers) is where HTTP API code lives and bridges it with component code.
|
||||
- [Controllers](./Controllers) is where REST API code lives.
|
||||
- [Core](./Core) contains [Application.cs](./Core/Application.cs) and other classes related to the overrarching server process.
|
||||
- [Database](./Database) contains all database related code.
|
||||
- [Extensions](./Extensions) contains helper functions implemented as C# extension methods.
|
||||
- [GraphQL](./GraqhQL) is where GraphQL API code lives.
|
||||
- [IO](./IO) contains classes related to interacting with the filesystem.
|
||||
- [Jobs](./Jobs) contains the job manager code.
|
||||
- [Models](./Models) contains ORM models used to interact with the database.
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<_Parameter4>$(TgsHostWatchdogVersion)</_Parameter4>
|
||||
<_Parameter5>$(TgsMariaDBRedistVersion)</_Parameter5>
|
||||
<_Parameter6>$(TgsSwarmProtocolVersion)</_Parameter6>
|
||||
<_Parameter7>$(TgsGraphQLVersion)</_Parameter7>
|
||||
</MasterVersionAssemblyAttributes>
|
||||
</ItemGroup>
|
||||
<WriteCodeFragment AssemblyAttributes="@(MasterVersionAssemblyAttributes)" Language="C#" OutputDirectory="$(IntermediateOutputPath)" OutputFile="MasterVersionsAssemblyInfo.cs">
|
||||
|
||||
@@ -13,7 +13,7 @@ General:
|
||||
UserGroupLimit: 25 # Maximum number of allowed groups
|
||||
InstanceLimit: 10 # Maximum number of allowed instances
|
||||
ValidInstancePaths: # An array of directories instances may be created in (either directly or as a subdirectory). null removes the restriction
|
||||
HostApiDocumentation: false # Make HTTP API documentation available at /api/doc/tgs_api.json
|
||||
HostApiDocumentation: false # Make HTTP API documentation available at /api/doc/tgs_api.json and /api/graphql
|
||||
SkipAddingByondFirewallException: false # Windows Only: Prevent running netsh.exe to add a firewall exception for installed engine binaries
|
||||
DeploymentDirectoryCopyTasksPerCore: 100 # Maximum number of concurrent file copy operations PER available CPU core
|
||||
OpenDreamGitUrl: https://github.com/OpenDreamProject/OpenDream # The repository to retrieve OpenDream from
|
||||
@@ -40,7 +40,7 @@ Logging:
|
||||
Microsoft: Warning # Level of stdout verbosity from Microsoft dependecies (i.e. webserver, database object relational mapper, etc...). Can be one of Trace, Debug, Information, Warning, Error, or Critical
|
||||
ControlPanel:
|
||||
Enable: false # If the web control panel is hosted alongside the server
|
||||
Channel: https://tgstation.github.io/tgstation-server-webpanel/api/${Major}.${Minor}.${Patch} # Channel for live web control panel updates. The tokens ${Major}, ${Minor}, and ${Patch} are substituted for the version of the HTTP API TGS was built with
|
||||
Channel: https://tgstation.github.io/tgstation-server-webpanel/api/${Major}.${Minor}.${Patch} # Channel for live web control panel updates. The tokens ${Major}, ${Minor}, and ${Patch} are substituted for the version of the REST API TGS was built with
|
||||
AllowAnyOrigin: false # Enable the `Access-Control-Allow-Origin: *` header for HTTP responses
|
||||
AllowedOrigins: [] # Explict list of origins for `Access-Control-Allow-Origin:` HTTP header. Ignored if AllowAnyOrigin is true
|
||||
PublicPath: # Used if TGS is not hosted at the website root. If TGS is hosted under `https://domain.com/tgs`, this should be `/tgs`
|
||||
|
||||
@@ -1402,24 +1402,8 @@ namespace Tgstation.Server.Tests.Live
|
||||
// test getting server info
|
||||
var unAuthedMultiClient = new MultiServerClient(firstAdminRestClient, unauthenticatedGraphQLClient);
|
||||
|
||||
await unAuthedMultiClient.ExecuteReadOnlyConfirmEquivalence(
|
||||
restClient => restClient.ServerInformation(cancellationToken),
|
||||
await unauthenticatedGraphQLClient.RunQueryEnsureNoErrors(
|
||||
gqlClient => gqlClient.UnauthenticatedServerInformation.ExecuteAsync(cancellationToken),
|
||||
(restServerInfo, gqlServerInfo) =>
|
||||
{
|
||||
var result = restServerInfo.ApiVersion.Major == gqlServerInfo.Swarm.CurrentNode.Gateway.Information.MajorApiVersion
|
||||
&& (restServerInfo.OAuthProviderInfos == gqlServerInfo.Swarm.CurrentNode.Gateway.Information.OAuthProviderInfos
|
||||
|| restServerInfo.OAuthProviderInfos.All(kvp =>
|
||||
{
|
||||
var info = gqlServerInfo.Swarm.CurrentNode.Gateway.Information.OAuthProviderInfos.FirstOrDefault(x => (int)x.Key == (int)kvp.Key);
|
||||
return info != null
|
||||
&& info.Value.ServerUrl == kvp.Value.ServerUrl
|
||||
&& info.Value.ClientId == kvp.Value.ClientId
|
||||
&& info.Value.RedirectUri == kvp.Value.RedirectUri;
|
||||
}));
|
||||
|
||||
return result;
|
||||
},
|
||||
cancellationToken);
|
||||
|
||||
var testObserver = new HoldLastObserver<IOperationResult<ISessionInvalidationResult>>();
|
||||
|
||||
@@ -32,7 +32,7 @@ using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Tests.Live;
|
||||
using Tgstation.Server.Host.Utils;
|
||||
using Tgstation.Server.Host.Properties;
|
||||
|
||||
namespace Tgstation.Server.Tests
|
||||
{
|
||||
@@ -75,14 +75,23 @@ namespace Tgstation.Server.Tests
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestApiVersion()
|
||||
public void TestRestVersion()
|
||||
{
|
||||
var versionString = versionsPropertyGroup.Element(xmlNamespace + "TgsApiVersion").Value;
|
||||
var versionString = versionsPropertyGroup.Element(xmlNamespace + "TgsRestVersion").Value;
|
||||
Assert.IsNotNull(versionString);
|
||||
Assert.IsTrue(Version.TryParse(versionString, out var expected));
|
||||
Assert.AreEqual(expected, ApiHeaders.Version);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestGraphQLVersion()
|
||||
{
|
||||
var versionString = versionsPropertyGroup.Element(xmlNamespace + "TgsGraphQLVersion").Value;
|
||||
Assert.IsNotNull(versionString);
|
||||
Assert.IsTrue(Version.TryParse(versionString, out var expected));
|
||||
Assert.AreEqual(expected, Version.Parse(MasterVersionsAttribute.Instance.RawGraphQLVersion));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestApiLibraryVersion()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Tgstation.Server.ReleaseNotes
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Tgstation.Server.ReleaseNotes
|
||||
{
|
||||
enum Component
|
||||
{
|
||||
@@ -6,7 +8,8 @@
|
||||
Core,
|
||||
HostWatchdog,
|
||||
WebControlPanel,
|
||||
HttpApi,
|
||||
HttpApi, // can't be properly renamed due to changelog
|
||||
GraphQLApi,
|
||||
DreamMakerApi,
|
||||
InteropApi,
|
||||
NugetCommon,
|
||||
|
||||
@@ -91,9 +91,12 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
case "--NO-CLOSE":
|
||||
doNotCloseMilestone = true;
|
||||
break;
|
||||
case "--HTTPAPI":
|
||||
case "--RESTAPI":
|
||||
componentRelease = Component.HttpApi;
|
||||
break;
|
||||
case "--GRAPHQLAPI":
|
||||
componentRelease = Component.GraphQLApi;
|
||||
break;
|
||||
case "--INTEROPAPI":
|
||||
componentRelease = Component.InteropApi;
|
||||
break;
|
||||
@@ -245,7 +248,8 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
return 10;
|
||||
}
|
||||
|
||||
var apiVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsApiVersion").Value);
|
||||
var restVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsRestVersion").Value);
|
||||
var graphQLVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsGraphQLVersion").Value);
|
||||
var configVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsConfigVersion").Value);
|
||||
var dmApiVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsDmapiVersion").Value);
|
||||
var interopVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsInteropVersion").Value);
|
||||
@@ -255,7 +259,7 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
if (webControlVersion.Major == 0)
|
||||
postControlPanelMessage = true;
|
||||
|
||||
prefix = $"Please refer to the [README](https://github.com/tgstation/tgstation-server#setup) for setup instructions. Full changelog can be found [here](https://raw.githubusercontent.com/tgstation/tgstation-server/gh-pages/changelog.yml).{Environment.NewLine}{Environment.NewLine}#### Component Versions\nCore: {coreVersion}\nConfiguration: {configVersion}\nHTTP API: {apiVersion}\nDreamMaker API: {dmApiVersion} (Interop: {interopVersion})\n[Web Control Panel](https://github.com/tgstation/tgstation-server-webpanel): {webControlVersion}\nHost Watchdog: {hostWatchdogVersion}";
|
||||
prefix = $"Please refer to the [README](https://github.com/tgstation/tgstation-server#setup) for setup instructions. Full changelog can be found [here](https://raw.githubusercontent.com/tgstation/tgstation-server/gh-pages/changelog.yml).{Environment.NewLine}{Environment.NewLine}#### Component Versions\nCore: {coreVersion}\nConfiguration: {configVersion}\nREST API: {restVersion}\nGraphQL API{(graphQLVersion.Major < 1 ? " (Pre-release)" : String.Empty)}: {graphQLVersion}\nDreamMaker API: {dmApiVersion} (Interop: {interopVersion})\n[Web Control Panel](https://github.com/tgstation/tgstation-server-webpanel): {webControlVersion}\nHost Watchdog: {hostWatchdogVersion}";
|
||||
|
||||
var newNotes = new StringBuilder(prefix);
|
||||
if (postControlPanelMessage)
|
||||
@@ -409,7 +413,8 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
var componentVersionDict = new Dictionary<Component, Version>
|
||||
{
|
||||
{ Component.Configuration, configVersion },
|
||||
{ Component.HttpApi, apiVersion },
|
||||
{ Component.HttpApi, restVersion },
|
||||
{ Component.GraphQLApi, graphQLVersion },
|
||||
{ Component.DreamMakerApi, dmApiVersion },
|
||||
{ Component.InteropApi, interopVersion },
|
||||
{ Component.WebControlPanel, webControlVersion },
|
||||
@@ -508,7 +513,8 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
|
||||
static string GetComponentDisplayName(Component component, bool debian) => component switch
|
||||
{
|
||||
Component.HttpApi => debian ? "the HTTP API" : "HTTP API",
|
||||
Component.HttpApi => debian ? "the REST API" : "REST API",
|
||||
Component.GraphQLApi => debian ? "the GraphQL API" : "GraphQL API",
|
||||
Component.InteropApi => debian ? "the Interop API" : "Interop API",
|
||||
Component.Configuration => debian ? "the TGS configuration" : "**Configuration**",
|
||||
Component.DreamMakerApi => debian ? "the DreamMaker API" : "DreamMaker API",
|
||||
@@ -607,7 +613,8 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
var dict = new Dictionary<Component, Version>
|
||||
{
|
||||
{ Component.Core, Parse("TgsCoreVersion") },
|
||||
{ Component.HttpApi, Parse("TgsApiVersion") },
|
||||
{ Component.HttpApi, Parse("TgsRestVersion") },
|
||||
{ Component.GraphQLApi, Parse("TgsGraphQLVersion") },
|
||||
{ Component.DreamMakerApi, Parse("TgsDmapiVersion") },
|
||||
};
|
||||
|
||||
@@ -720,7 +727,8 @@ namespace Tgstation.Server.ReleaseNotes
|
||||
component = targetComponent.ToUpperInvariant() switch
|
||||
{
|
||||
"**CONFIGURATION**" or "CONFIGURATION" or "CONFIG" => Component.Configuration,
|
||||
"HTTP API" => Component.HttpApi,
|
||||
"HTTP API" or "REST API" => Component.HttpApi,
|
||||
"GQL API" or "GRAPHQL API" or "GQL" or "GRAPHQL" => Component.GraphQLApi,
|
||||
"WEB CONTROL PANEL" => Component.WebControlPanel,
|
||||
"DMAPI" or "DREAMMAKER API" => Component.DreamMakerApi,
|
||||
"INTEROP API" => Component.InteropApi,
|
||||
@@ -1160,15 +1168,23 @@ Note: `<path>` is the directory's name containing the manifest you're submitting
|
||||
var nugetApiVersions = EnumerateNugetVersions("Tgstation.Server.Api");
|
||||
var nugetClientVersions = EnumerateNugetVersions("Tgstation.Server.Client");
|
||||
|
||||
const string ApiTagPrefix = "api-v";
|
||||
const string GraphQLTagPrefix = "graphql-v";
|
||||
const string DMApiTagPrefix = "dmapi-v";
|
||||
var newDic = new Dictionary<Component, IReadOnlySet<Version>> {
|
||||
{ Component.HttpApi, releases
|
||||
.Where(x => x.TagName.StartsWith("api-v"))
|
||||
.Select(x => Version.Parse(x.TagName[5..]))
|
||||
.Where(x => x.TagName.StartsWith(ApiTagPrefix))
|
||||
.Select(x => Version.Parse(x.TagName[ApiTagPrefix.Length..]))
|
||||
.OrderBy(x => x)
|
||||
.ToHashSet() },
|
||||
{ Component.GraphQLApi, releases
|
||||
.Where(x => x.TagName.StartsWith(GraphQLTagPrefix))
|
||||
.Select(x => Version.Parse(x.TagName[GraphQLTagPrefix.Length..]))
|
||||
.OrderBy(x => x)
|
||||
.ToHashSet() },
|
||||
{ Component.DreamMakerApi, releases
|
||||
.Where(x => x.TagName.StartsWith("dmapi-v"))
|
||||
.Select(x => Version.Parse(x.TagName[7..]))
|
||||
.Where(x => x.TagName.StartsWith(DMApiTagPrefix))
|
||||
.Select(x => Version.Parse(x.TagName[DMApiTagPrefix.Length..]))
|
||||
.OrderBy(x => x)
|
||||
.ToHashSet() },
|
||||
{ Component.NugetCommon, await nugetCommonVersions },
|
||||
|
||||
Reference in New Issue
Block a user