diff --git a/package.json b/package.json index ce785a67..ab6c8e4a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tgstation-server-control-panel", "version": "5.0.0", - "tgs_api_version": "9.13.0", + "tgs_api_version": "10.0.0", "private": true, "homepage": "https://tgstation.github.io/tgstation-server-control-panel", "repository": "github:tgstation/tgstation-server-control-panel", @@ -47,6 +47,7 @@ "fs-extra": "^9.1.0", "https-browserify": "^1.0.0", "jquery": "^3.5.1", + "jwt-decode": "^4.0.0", "path-to-regexp": "^6.2.0", "popper.js": "^1.16.1", "prettier": "2.2.1", diff --git a/src/ApiClient/AdminClient.ts b/src/ApiClient/AdminClient.ts index 9fdf3599..ae569402 100644 --- a/src/ApiClient/AdminClient.ts +++ b/src/ApiClient/AdminClient.ts @@ -72,7 +72,7 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerRead(); + response = await ServerClient.apiClient!.api.administrationControllerRead(); } catch (stat) { const res = new InternalStatus({ code: StatusCode.ERROR, @@ -153,7 +153,7 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerDelete(); + response = await ServerClient.apiClient!.api.administrationControllerDelete(); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -199,7 +199,7 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerUpdate({ + response = await ServerClient.apiClient!.api.administrationControllerUpdate({ newVersion }); } catch (stat) { @@ -281,7 +281,7 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerUpdate({ + response = await ServerClient.apiClient!.api.administrationControllerUpdate({ newVersion, uploadZip: true }); @@ -373,12 +373,10 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerListLogs( - { - pageSize: pageSize, - page: page - } - ); + response = await ServerClient.apiClient!.api.administrationControllerListLogs({ + pageSize: pageSize, + page: page + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -424,9 +422,7 @@ export default new (class AdminClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.administration.administrationControllerGetLog( - logName - ); + response = await ServerClient.apiClient!.api.administrationControllerGetLog(logName); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, diff --git a/src/ApiClient/ChatBotClient.ts b/src/ApiClient/ChatBotClient.ts index 438bbca4..772a47a9 100644 --- a/src/ApiClient/ChatBotClient.ts +++ b/src/ApiClient/ChatBotClient.ts @@ -26,7 +26,7 @@ export default new (class ChatBotClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.chat.chatControllerList( + response = await ServerClient.apiClient!.api.chatControllerList( { page, pageSize }, { headers: { @@ -69,7 +69,7 @@ export default new (class ChatBotClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.chat.chatControllerCreate(chatBot, { + response = await ServerClient.apiClient!.api.chatControllerCreate(chatBot, { headers: { Instance: instance.toString() } @@ -109,7 +109,7 @@ export default new (class ChatBotClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.chat.chatControllerUpdate(chatBot, { + response = await ServerClient.apiClient!.api.chatControllerUpdate(chatBot, { headers: { Instance: instance.toString() } @@ -167,7 +167,7 @@ export default new (class ChatBotClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.chat.chatControllerGetId(chatBotId, { + response = await ServerClient.apiClient!.api.chatControllerGetId(chatBotId, { headers: { Instance: instance.toString() } @@ -219,7 +219,7 @@ export default new (class ChatBotClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.chat.chatControllerDelete(chatBotId, { + response = await ServerClient.apiClient!.api.chatControllerDelete(chatBotId, { headers: { Instance: instance.toString() } diff --git a/src/ApiClient/ConfigurationFileClient.ts b/src/ApiClient/ConfigurationFileClient.ts index 9de34a85..a99e0113 100644 --- a/src/ApiClient/ConfigurationFileClient.ts +++ b/src/ApiClient/ConfigurationFileClient.ts @@ -28,7 +28,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerCreateDirectory( + response = await ServerClient.apiClient!.api.configurationControllerCreateDirectory( path, { headers: { @@ -73,7 +73,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerUpdate( + response = await ServerClient.apiClient!.api.configurationControllerUpdate( fileRequest, { headers: { Instance: instance.toString() } @@ -120,7 +120,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerFile(filePath, { + response = await ServerClient.apiClient!.api.configurationControllerFile(filePath, { headers: { Instance: instance.toString() } }); } catch (stat) { @@ -187,7 +187,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerDirectory( + response = await ServerClient.apiClient!.api.configurationControllerDirectory( { directoryPath, pageSize: pageSize, @@ -242,7 +242,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerList( + response = await ServerClient.apiClient!.api.configurationControllerList( { pageSize: pageSize, page: page @@ -284,7 +284,7 @@ export default new (class ConfigurationFileClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.config.configurationControllerDeleteDirectory( + response = await ServerClient.apiClient!.api.configurationControllerDeleteDirectory( directory, { headers: { Instance: instance.toString() } } ); diff --git a/src/ApiClient/DreamDaemonClient.ts b/src/ApiClient/DreamDaemonClient.ts index 86f9e911..2f669c0f 100644 --- a/src/ApiClient/DreamDaemonClient.ts +++ b/src/ApiClient/DreamDaemonClient.ts @@ -19,7 +19,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerRead({ + response = await ServerClient.apiClient!.api.dreamDaemonControllerRead({ headers: { Instance: instance.toString() } @@ -71,14 +71,11 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerUpdate( - newSettings, - { - headers: { - Instance: instance.toString() - } + response = await ServerClient.apiClient!.api.dreamDaemonControllerUpdate(newSettings, { + headers: { + Instance: instance.toString() } - ); + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -125,7 +122,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerCreate({ + response = await ServerClient.apiClient!.api.dreamDaemonControllerCreate({ headers: { Instance: instance.toString() } @@ -162,7 +159,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerDelete({ + response = await ServerClient.apiClient!.api.dreamDaemonControllerDelete({ headers: { Instance: instance.toString() } @@ -201,7 +198,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerRestart({ + response = await ServerClient.apiClient!.api.dreamDaemonControllerRestart({ headers: { Instance: instance.toString() } @@ -240,7 +237,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamDaemon.dreamDaemonControllerCreateDump({ + response = await ServerClient.apiClient!.api.dreamDaemonControllerCreateDump({ headers: { Instance: instance.toString() } diff --git a/src/ApiClient/DreamMakerClient.ts b/src/ApiClient/DreamMakerClient.ts index 3f41f0c5..02430812 100644 --- a/src/ApiClient/DreamMakerClient.ts +++ b/src/ApiClient/DreamMakerClient.ts @@ -26,7 +26,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamMaker.dreamMakerControllerRead({ + response = await ServerClient.apiClient!.api.dreamMakerControllerRead({ headers: { Instance: instance.toString() } @@ -65,7 +65,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamMaker.dreamMakerControllerCreate({ + response = await ServerClient.apiClient!.api.dreamMakerControllerCreate({ headers: { Instance: instance.toString() } @@ -105,14 +105,11 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamMaker.dreamMakerControllerUpdate( - settings, - { - headers: { - Instance: instance.toString() - } + response = await ServerClient.apiClient!.api.dreamMakerControllerUpdate(settings, { + headers: { + Instance: instance.toString() } - ); + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -166,7 +163,7 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamMaker.dreamMakerControllerList( + response = await ServerClient.apiClient!.api.dreamMakerControllerList( { page, pageSize }, { headers: { @@ -209,14 +206,11 @@ export default new (class DreamDaemonClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.dreamMaker.dreamMakerControllerGetId( - compileJob, - { - headers: { - Instance: instance.toString() - } + response = await ServerClient.apiClient!.api.dreamMakerControllerGetId(compileJob, { + headers: { + Instance: instance.toString() } - ); + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, diff --git a/src/ApiClient/ByondClient.ts b/src/ApiClient/EngineClient.ts similarity index 85% rename from src/ApiClient/ByondClient.ts rename to src/ApiClient/EngineClient.ts index d01252f6..0c5357c4 100644 --- a/src/ApiClient/ByondClient.ts +++ b/src/ApiClient/EngineClient.ts @@ -1,10 +1,11 @@ import { ApiClient } from "./_base"; import { - ByondInstallResponse, - ByondResponse, + EngineInstallResponse, + EngineResponse, + EngineVersion, ErrorMessageResponse, JobResponse, - PaginatedByondResponse + PaginatedEngineResponse } from "./generatedcode/generated"; import InternalError, { ErrorCode, GenericErrors } from "./models/InternalComms/InternalError"; import InternalStatus, { StatusCode } from "./models/InternalComms/InternalStatus"; @@ -12,17 +13,17 @@ import ServerClient from "./ServerClient"; import TransferClient, { UploadErrors } from "./TransferClient"; import configOptions from "./util/config"; -export type DeleteErrors = GenericErrors | ErrorCode.BYOND_VERSION_NOT_FOUND; +export type DeleteErrors = GenericErrors | ErrorCode.ENGINE_VERSION_NOT_FOUND; -export default new (class ByondClient extends ApiClient { +export default new (class EngineClient extends ApiClient { public async getActiveVersion( instance: number - ): Promise> { + ): Promise> { await ServerClient.wait4Init(); let response; try { - response = await ServerClient.apiClient!.byond.byondControllerRead({ + response = await ServerClient.apiClient!.api.engineControllerRead({ headers: { Instance: instance.toString() } @@ -38,7 +39,7 @@ export default new (class ByondClient extends ApiClient { case 200: { return new InternalStatus({ code: StatusCode.OK, - payload: response.data as ByondResponse + payload: response.data as EngineResponse }); } default: { @@ -57,12 +58,12 @@ export default new (class ByondClient extends ApiClient { public async listAllVersions( instance: number, { page = 1, pageSize = configOptions.itemsperpage.value as number } - ): Promise> { + ): Promise> { await ServerClient.wait4Init(); let response; try { - response = await ServerClient.apiClient!.byond.byondControllerList( + response = await ServerClient.apiClient!.api.engineControllerList( { page: page, pageSize: pageSize @@ -84,7 +85,7 @@ export default new (class ByondClient extends ApiClient { case 200: { return new InternalStatus({ code: StatusCode.OK, - payload: response.data as PaginatedByondResponse + payload: response.data as PaginatedEngineResponse }); } default: { @@ -102,15 +103,15 @@ export default new (class ByondClient extends ApiClient { public async deleteVersion( instance: number, - version: string + engineVersion: EngineVersion ): Promise> { await ServerClient.wait4Init(); let response; try { - response = await ServerClient.apiClient!.byond.byondControllerDelete( + response = await ServerClient.apiClient!.api.engineControllerDelete( { - version + engineVersion }, { headers: { @@ -144,7 +145,7 @@ export default new (class ByondClient extends ApiClient { return new InternalStatus({ code: StatusCode.ERROR, error: new InternalError( - ErrorCode.BYOND_VERSION_NOT_FOUND, + ErrorCode.ENGINE_VERSION_NOT_FOUND, { errorMessage: response.data as ErrorMessageResponse }, @@ -167,16 +168,16 @@ export default new (class ByondClient extends ApiClient { public async switchActive( instance: number, - version: string, + engineVersion: EngineVersion, file?: ArrayBuffer - ): Promise> { + ): Promise> { await ServerClient.wait4Init(); let response; try { - response = await ServerClient.apiClient!.byond.byondControllerUpdate( + response = await ServerClient.apiClient!.api.engineControllerUpdate( { - version: version, + engineVersion, uploadCustomZip: !!file }, { @@ -195,7 +196,7 @@ export default new (class ByondClient extends ApiClient { switch (response.status) { case 200: case 202: { - const responseData = response.data as ByondInstallResponse; + const responseData = response.data as EngineInstallResponse; if (responseData.fileTicket) { if (file) { const response2 = await TransferClient.Upload( diff --git a/src/ApiClient/InstanceClient.ts b/src/ApiClient/InstanceClient.ts index e8227485..67f39379 100644 --- a/src/ApiClient/InstanceClient.ts +++ b/src/ApiClient/InstanceClient.ts @@ -31,7 +31,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerList({ + response = await ServerClient.apiClient!.api.instanceControllerList({ pageSize: pageSize, page: page }); @@ -69,7 +69,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerGrantPermissions( + response = await ServerClient.apiClient!.api.instanceControllerGrantPermissions( instance.id ); this.emit("instanceChange", instance.id); @@ -113,7 +113,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerUpdate(instance); + response = await ServerClient.apiClient!.api.instanceControllerUpdate(instance); this.emit("instanceChange", instance.id); } catch (stat) { return new InternalStatus({ @@ -154,7 +154,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerDelete(id); + response = await ServerClient.apiClient!.api.instanceControllerDelete(id); this.emit("instanceChange", id); } catch (stat) { return new InternalStatus({ @@ -196,7 +196,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerCreate(instance); + response = await ServerClient.apiClient!.api.instanceControllerCreate(instance); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -242,7 +242,7 @@ export default new (class InstanceClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.instance.instanceControllerGetId(instanceid); + response = await ServerClient.apiClient!.api.instanceControllerGetId(instanceid); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, diff --git a/src/ApiClient/InstancePermissionSetClient.ts b/src/ApiClient/InstancePermissionSetClient.ts index a0f5c568..e49451b5 100644 --- a/src/ApiClient/InstancePermissionSetClient.ts +++ b/src/ApiClient/InstancePermissionSetClient.ts @@ -49,7 +49,7 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerList( + response = await ServerClient.apiClient!.api.instancePermissionSetControllerList( { page: page, pageSize: pageSize @@ -123,13 +123,11 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerRead( - { - headers: { - Instance: instanceid.toString() - } + response = await ServerClient.apiClient!.api.instancePermissionSetControllerRead({ + headers: { + Instance: instanceid.toString() } - ); + }); } catch (stat) { const res = new InternalStatus({ code: StatusCode.ERROR, @@ -176,7 +174,7 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerGetId( + response = await ServerClient.apiClient!.api.instancePermissionSetControllerGetId( permissionSetId, { headers: { @@ -235,7 +233,7 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerCreate( + response = await ServerClient.apiClient!.api.instancePermissionSetControllerCreate( instancePermissionSet, { headers: { @@ -294,7 +292,7 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerUpdate( + response = await ServerClient.apiClient!.api.instancePermissionSetControllerUpdate( instancePermissionSet, { headers: { @@ -353,7 +351,7 @@ export default new (class InstancePermissionSetClient extends ApiClient let response; try { - response = await ServerClient.apiClient!.instancePermissionSet.instancePermissionSetControllerDelete( + response = await ServerClient.apiClient!.api.instancePermissionSetControllerDelete( permissionSetId, { headers: { diff --git a/src/ApiClient/JobsClient.ts b/src/ApiClient/JobsClient.ts index 8db1a05b..fd70351a 100644 --- a/src/ApiClient/JobsClient.ts +++ b/src/ApiClient/JobsClient.ts @@ -32,7 +32,7 @@ export default new (class JobsClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.job.jobControllerRead( + response = await ServerClient.apiClient!.api.jobControllerRead( { page: page, pageSize: pageSize @@ -88,7 +88,7 @@ export default new (class JobsClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.job.jobControllerGetId(jobid, { + response = await ServerClient.apiClient!.api.jobControllerGetId(jobid, { headers: { Instance: instanceid.toString() } @@ -140,7 +140,7 @@ export default new (class JobsClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.job.jobControllerDelete(jobid, { + response = await ServerClient.apiClient!.api.jobControllerDelete(jobid, { headers: { Instance: instanceid.toString() } @@ -200,7 +200,7 @@ export default new (class JobsClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.job.jobControllerList( + response = await ServerClient.apiClient!.api.jobControllerList( { pageSize, page diff --git a/src/ApiClient/RepositoryClient.ts b/src/ApiClient/RepositoryClient.ts index 468117a4..d3fccb99 100644 --- a/src/ApiClient/RepositoryClient.ts +++ b/src/ApiClient/RepositoryClient.ts @@ -23,14 +23,11 @@ export default new (class RepositoryClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.repository.repositoryControllerCreate( - settings, - { - headers: { - Instance: instanceid - } + response = await ServerClient.apiClient!.api.repositoryControllerCreate(settings, { + headers: { + Instance: instanceid } - ); + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -77,7 +74,7 @@ export default new (class RepositoryClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.repository.repositoryControllerDelete({ + response = await ServerClient.apiClient!.api.repositoryControllerDelete({ headers: { Instance: instanceid } @@ -130,7 +127,7 @@ export default new (class RepositoryClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.repository.repositoryControllerRead({ + response = await ServerClient.apiClient!.api.repositoryControllerRead({ headers: { Instance: instanceid } @@ -193,14 +190,11 @@ export default new (class RepositoryClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.repository.repositoryControllerUpdate( - newSettings, - { - headers: { - Instance: instanceid - } + response = await ServerClient.apiClient!.api.repositoryControllerUpdate(newSettings, { + headers: { + Instance: instanceid } - ); + }); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, diff --git a/src/ApiClient/ServerClient.ts b/src/ApiClient/ServerClient.ts index 01d9e6df..f87ba973 100644 --- a/src/ApiClient/ServerClient.ts +++ b/src/ApiClient/ServerClient.ts @@ -1,4 +1,5 @@ import { AxiosError, AxiosInstance, AxiosResponse } from "axios"; +import { jwtDecode } from "jwt-decode"; import { API_VERSION, VERSION } from "../definitions/constants"; import { ApiClient } from "./_base"; @@ -67,7 +68,7 @@ export default new (class ServerClient extends ApiClient { //This applies the authorization header, it will wait however long it needs until // theres a token available. It obviously won't wait for a token before sending the request // if its currently sending a request to the login endpoint... - if (value.overrideTokenDetection || !(value.url === "/" || value.url === "")) { + if (value.overrideTokenDetection || !(value.url === "/api" || value.url === "/api/")) { const tok = await this.wait4Token(); (value.headers as { [key: string]: string })["Authorization"] = `Bearer ${ tok.bearer || "" @@ -326,12 +327,12 @@ export default new (class ServerClient extends ApiClient { let result = false; // check if there's a token stored const bearer = localStorage.getItem("SessionToken"); - const expiresAt = localStorage.getItem("SessionTokenExpiry"); + const expiresAtUnixTimestampStr = localStorage.getItem("SessionTokenExpiry"); const defaultToken = localStorage.getItem("SessionTokenDefault") == "true"; - if (bearer && expiresAt) { + if (bearer && expiresAtUnixTimestampStr) { console.log("Found session token"); - if (Date.parse(expiresAt) >= Date.now()) { - const storedToken: TokenResponse = { bearer, expiresAt }; + if (parseInt(expiresAtUnixTimestampStr) * 1000 >= Date.now()) { + const storedToken: TokenResponse = { bearer }; result = await this.setToken(storedToken, defaultToken, true); } else { console.log("But it was expired"); @@ -419,7 +420,7 @@ export default new (class ServerClient extends ApiClient { CredentialsProvider.default.userName.toLowerCase() && CredentialsProvider.credentials.password == CredentialsProvider.default.password; - response = await this.apiClient!.homeControllerCreateToken({ + response = await this.apiClient!.api.apiRootControllerCreateToken({ auth: { username: CredentialsProvider.credentials.userName, password: CredentialsProvider.credentials.password @@ -427,7 +428,7 @@ export default new (class ServerClient extends ApiClient { }); } else { defaulted = false; - response = await this.apiClient!.homeControllerCreateToken({ + response = await this.apiClient!.api.apiRootControllerCreateToken({ headers: { OAuthProvider: CredentialsProvider.credentials.provider, Authorization: `OAuth ${CredentialsProvider.credentials.token}` @@ -568,7 +569,7 @@ export default new (class ServerClient extends ApiClient { let response; try { - response = await this.apiClient!.homeControllerHome(); + response = await this.apiClient!.api.apiRootControllerServerInfo(); } catch (stat) { const res = new InternalStatus({ code: StatusCode.ERROR, @@ -625,7 +626,7 @@ export default new (class ServerClient extends ApiClient { if (validate) { let failed; try { - const response = await this.apiClient!.homeControllerHome({ + const response = await this.apiClient!.api.apiRootControllerServerInfo({ overrideTokenDetection: true }); @@ -645,7 +646,11 @@ export default new (class ServerClient extends ApiClient { } localStorage.setItem("SessionToken", token.bearer); - localStorage.setItem("SessionTokenExpiry", token.expiresAt); + const jwt = jwtDecode(token.bearer); + if (jwt.exp) { + localStorage.setItem("SessionTokenExpiry", jwt.exp.toString()); + } + localStorage.setItem("SessionTokenDefault", defaulted ? "true" : "false"); this.emit("tokenAvailable", token); diff --git a/src/ApiClient/TransferClient.ts b/src/ApiClient/TransferClient.ts index a94a5824..de413f35 100644 --- a/src/ApiClient/TransferClient.ts +++ b/src/ApiClient/TransferClient.ts @@ -16,7 +16,7 @@ export default new (class TransferClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.transfer.transferControllerDownload( + response = await ServerClient.apiClient!.api.transferControllerDownload( { ticket: ticket }, @@ -70,7 +70,7 @@ export default new (class TransferClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.transfer.transferControllerUpload( + response = await ServerClient.apiClient!.api.transferControllerUpload( { ticket: ticket }, diff --git a/src/ApiClient/UserClient.ts b/src/ApiClient/UserClient.ts index d1a1df76..d5863bcc 100644 --- a/src/ApiClient/UserClient.ts +++ b/src/ApiClient/UserClient.ts @@ -48,7 +48,7 @@ export default new (class UserClient extends ApiClient { await ServerClient.wait4Init(); let response; try { - response = await ServerClient.apiClient!.user.userControllerUpdate(newUser); + response = await ServerClient.apiClient!.api.userControllerUpdate(newUser); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -119,7 +119,7 @@ export default new (class UserClient extends ApiClient { let response; try { // UserController_Read - response = await ServerClient.apiClient!.user.userControllerRead(); + response = await ServerClient.apiClient!.api.userControllerRead(); } catch (stat) { const res = new InternalStatus({ code: StatusCode.ERROR, @@ -166,7 +166,7 @@ export default new (class UserClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.user.userControllerList({ + response = await ServerClient.apiClient!.api.userControllerList({ page: page, pageSize: pageSize }); @@ -209,7 +209,7 @@ export default new (class UserClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.user.userControllerGetId(id); + response = await ServerClient.apiClient!.api.userControllerGetId(id); } catch (stat) { return new InternalStatus({ code: StatusCode.ERROR, @@ -280,7 +280,7 @@ export default new (class UserClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.user.userControllerCreate( + response = await ServerClient.apiClient!.api.userControllerCreate( newuser as UserCreateRequest ); } catch (stat) { diff --git a/src/ApiClient/UserGroupClient.ts b/src/ApiClient/UserGroupClient.ts index 8570222f..7fe55582 100644 --- a/src/ApiClient/UserGroupClient.ts +++ b/src/ApiClient/UserGroupClient.ts @@ -28,7 +28,7 @@ export default new (class UserGroupClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.userGroup.userGroupControllerUpdate(group); + response = await ServerClient.apiClient!.api.userGroupControllerUpdate(group); } catch (e) { return new InternalStatus({ code: StatusCode.ERROR, @@ -72,7 +72,7 @@ export default new (class UserGroupClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.userGroup.userGroupControllerList({ + response = await ServerClient.apiClient!.api.userGroupControllerList({ pageSize: pageSize, page: page }); @@ -111,7 +111,7 @@ export default new (class UserGroupClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.userGroup.userGroupControllerCreate({ + response = await ServerClient.apiClient!.api.userGroupControllerCreate({ name: name, permissionSet: permissionSet } as UserGroupCreateRequest); @@ -147,7 +147,7 @@ export default new (class UserGroupClient extends ApiClient { let response; try { - response = await ServerClient.apiClient!.userGroup.userGroupControllerDelete(id); + response = await ServerClient.apiClient!.api.userGroupControllerDelete(id); } catch (e) { return new InternalStatus({ code: StatusCode.ERROR, diff --git a/src/ApiClient/models/InternalComms/InternalError.ts b/src/ApiClient/models/InternalComms/InternalError.ts index d868cfff..37283c55 100644 --- a/src/ApiClient/models/InternalComms/InternalError.ts +++ b/src/ApiClient/models/InternalComms/InternalError.ts @@ -72,8 +72,8 @@ export enum ErrorCode { //Watchdog errors NO_DB_ENTITY = "error.no_db_entity", //errmessage - //BYOND errors - BYOND_VERSION_NOT_FOUND = "error.no_byond_version", + //Engine errors + ENGINE_VERSION_NOT_FOUND = "error.no_engine_version", //DreamMaker errors COMPILE_JOB_NOT_FOUND = "error.compile_job_not_found", //errmessage diff --git a/src/ApiClient/util/JobsController.ts b/src/ApiClient/util/JobsController.ts index 0d665aa0..ae6821b5 100644 --- a/src/ApiClient/util/JobsController.ts +++ b/src/ApiClient/util/JobsController.ts @@ -5,11 +5,11 @@ import { TypedEmitter } from "tiny-typed-emitter"; import { resolvePermissionSet } from "../../utils/misc"; import { AdministrationRights, - ByondRights, ChatBotRights, ConfigurationRights, DreamDaemonRights, DreamMakerRights, + EngineRights, ErrorCode as TGSErrorCode, InstanceManagerRights, InstancePermissionSetRights, @@ -242,7 +242,7 @@ export default new (class JobsController extends TypedEmitter { } const localConnection = (this.connection = new signalR.HubConnectionBuilder() - .withUrl(`${apiPath}hubs/jobs`, { + .withUrl(`${apiPath}api/hubs/jobs`, { accessTokenFactory: async () => { const token = await ServerClient.wait4Token(); return token.bearer; @@ -632,13 +632,13 @@ export default new (class JobsController extends TypedEmitter { return false; } } - case RightsType.Byond: { + case RightsType.Engine: { const InstancePermissionSet = await InstancePermissionSetClient.getCurrentInstancePermissionSet( job.instanceId ); if (InstancePermissionSet.code === StatusCode.OK) { - const required = job.cancelRight as ByondRights; - return !!(InstancePermissionSet.payload.byondRights & required); + const required = job.cancelRight as EngineRights; + return !!(InstancePermissionSet.payload.engineRights & required); } else { errors.push(InstancePermissionSet.error); return false; diff --git a/src/components/utils/DeploymentViewer.tsx b/src/components/utils/DeploymentViewer.tsx index a72b3ff3..3303e9de 100644 --- a/src/components/utils/DeploymentViewer.tsx +++ b/src/components/utils/DeploymentViewer.tsx @@ -11,6 +11,7 @@ import { lt as SemverLessThan } from "semver"; import { CompileJobResponse, DreamDaemonSecurity } from "../../ApiClient/generatedcode/generated"; import { InstanceEditContext } from "../../contexts/InstanceEditContext"; +import Engine from "../views/Instance/Edit/Engine"; import { DebugJsonViewer } from "./JsonViewer"; import Loading from "./Loading"; import PageHelper from "./PageHelper"; @@ -216,12 +217,7 @@ class DeploymentViewer extends React.Component { } private renderCompileJob(compileJob: CompileJobResponse) { - let correctedByondVersion = compileJob.byondVersion; - if (correctedByondVersion.endsWith(".0")) - correctedByondVersion = correctedByondVersion.substring( - 0, - correctedByondVersion.length - 2 - ); + const engineVersion = Engine.friendlyVersion(compileJob.engineVersion); // we use en-GB so we get the fucking SANE DD/MM/YYYY const dateFormatter: Intl.DateTimeFormatOptions = { @@ -326,7 +322,7 @@ class DeploymentViewer extends React.Component { ) : null} {compileJob.id} - {correctedByondVersion} + {engineVersion} {new Date(compileJob.job.startedAt).toLocaleString("en-CA", dateFormatter)} diff --git a/src/components/views/Instance/Create.tsx b/src/components/views/Instance/Create.tsx index e50801f3..fdfceeb4 100644 --- a/src/components/views/Instance/Create.tsx +++ b/src/components/views/Instance/Create.tsx @@ -8,11 +8,15 @@ import { FormattedMessage } from "react-intl"; import { RouteComponentProps, withRouter } from "react-router-dom"; import YAML from "yaml"; -import ByondClient from "../../../ApiClient/ByondClient"; import ConfigurationFileClient from "../../../ApiClient/ConfigurationFileClient"; import DreamDaemonClient from "../../../ApiClient/DreamDaemonClient"; import DreamMakerClient from "../../../ApiClient/DreamMakerClient"; -import { ConfigurationType, DreamDaemonSecurity } from "../../../ApiClient/generatedcode/generated"; +import EngineClient from "../../../ApiClient/EngineClient"; +import { + ConfigurationType, + DreamDaemonSecurity, + EngineType +} from "../../../ApiClient/generatedcode/generated"; import InstanceClient from "../../../ApiClient/InstanceClient"; import InternalError, { ErrorCode } from "../../../ApiClient/models/InternalComms/InternalError"; import { StatusCode } from "../../../ApiClient/models/InternalComms/InternalStatus"; @@ -541,10 +545,13 @@ class InstanceCreate extends React.Component { values={{ version: yml.byond }} /> ); - const byondResult = await ByondClient.switchActive(instanceId, yml.byond); + const engineResult = await EngineClient.switchActive(instanceId, { + version: yml.byond, + engine: EngineType.Byond + }); - if (byondResult.code === StatusCode.ERROR) { - this.addError(byondResult.error); + if (engineResult.code === StatusCode.ERROR) { + this.addError(engineResult.error); this.setState({ performingQuickSetup: false }); @@ -552,7 +559,7 @@ class InstanceCreate extends React.Component { return; } - JobsController.registerJob(byondResult.payload.installJob!, instanceId); + JobsController.registerJob(engineResult.payload.installJob!, instanceId); } if (secLevel != DreamDaemonSecurity.Safe) { diff --git a/src/components/views/Instance/Edit/Byond.tsx b/src/components/views/Instance/Edit/Engine.tsx similarity index 51% rename from src/components/views/Instance/Edit/Byond.tsx rename to src/components/views/Instance/Edit/Engine.tsx index fab2efdd..87c32bf5 100644 --- a/src/components/views/Instance/Edit/Byond.tsx +++ b/src/components/views/Instance/Edit/Engine.tsx @@ -9,13 +9,19 @@ import OverlayTrigger from "react-bootstrap/OverlayTrigger"; import Tooltip from "react-bootstrap/Tooltip"; import { FormattedMessage } from "react-intl"; -import ByondClient from "../../../../ApiClient/ByondClient"; -import { ByondResponse, ByondRights } from "../../../../ApiClient/generatedcode/generated"; +import EngineClient from "../../../../ApiClient/EngineClient"; +import { + EngineResponse, + EngineRights, + EngineType, + EngineVersion +} from "../../../../ApiClient/generatedcode/generated"; import InternalError, { ErrorCode } from "../../../../ApiClient/models/InternalComms/InternalError"; import { StatusCode } from "../../../../ApiClient/models/InternalComms/InternalStatus"; import JobsController from "../../../../ApiClient/util/JobsController"; import { InstanceEditContext } from "../../../../contexts/InstanceEditContext"; -import { hasByondRight } from "../../../../utils/misc"; +import GithubClient from "../../../../utils/GithubClient"; +import { hasEngineRight } from "../../../../utils/misc"; import { RouteData } from "../../../../utils/routes"; import ErrorAlert from "../../../utils/ErrorAlert"; import GenericAlert from "../../../utils/GenericAlert"; @@ -27,27 +33,36 @@ interface IProps {} interface IState { errors: Array | undefined>; - versions: ByondResponse[]; - activeVersion?: string | null; - latestVersion: string; - selectedVersion: string; + versions: EngineResponse[]; + activeVersion?: EngineVersion; + latestByondVersion: EngineVersion; + latestODVersion: EngineVersion; + selectedByondVersion?: EngineVersion; + selectedODVersion?: EngineVersion; loading: boolean; customFile?: File | null; page: number; maxPage?: number; } -class Byond extends React.Component { +class Engine extends React.Component { public declare context: InstanceEditContext; public constructor(props: IProps) { super(props); + const initByond = { + version: "514.1589", + engine: EngineType.Byond + }; + const initOD = { + engine: EngineType.OpenDream, + sourceSHA: "fab769776dada6b9bcad546094d78c604049e0e9" + }; this.state = { versions: [], errors: [], - activeVersion: "", - latestVersion: "", - selectedVersion: "", + latestByondVersion: initByond, + latestODVersion: initOD, loading: true, page: RouteData.byondlistpage ?? 1 }; @@ -64,8 +79,8 @@ class Byond extends React.Component { } private async loadVersions() { - if (hasByondRight(this.context.instancePermissionSet, ByondRights.ListInstalled)) { - const response = await ByondClient.listAllVersions(this.context.instance.id, { + if (hasEngineRight(this.context.instancePermissionSet, EngineRights.ListInstalled)) { + const response = await EngineClient.listAllVersions(this.context.instance.id, { page: this.state.page }); if (response.code === StatusCode.OK) { @@ -88,11 +103,11 @@ class Byond extends React.Component { } } - if (hasByondRight(this.context.instancePermissionSet, ByondRights.ReadActive)) { - const response2 = await ByondClient.getActiveVersion(this.context.instance.id); + if (hasEngineRight(this.context.instancePermissionSet, EngineRights.ReadActive)) { + const response2 = await EngineClient.getActiveVersion(this.context.instance.id); if (response2.code === StatusCode.OK) { this.setState({ - activeVersion: response2.payload.version + activeVersion: response2.payload.engineVersion }); } else { this.addError(response2.error); @@ -100,11 +115,11 @@ class Byond extends React.Component { } } - private async switchVersion(version: string, useCustom: boolean): Promise { + private async switchVersion(version: EngineVersion, useCustom: boolean): Promise { this.setState({ loading: true }); - const response = await ByondClient.switchActive( + const response = await EngineClient.switchActive( this.context.instance.id, version, useCustom && this.state.customFile @@ -145,16 +160,19 @@ class Byond extends React.Component { } public async componentDidMount(): Promise { - await this.loadVersions(); - + const odGetPromise = GithubClient.getLatestDefaultCommit("OpenDreamProject", "OpenDream"); fetch("https://secure.byond.com/download/version.txt") .then(res => res.text()) .then(data => data.split("\n")) .then(versions => versions[0]) .then(version => { + const engineVersion: EngineVersion = { + engine: EngineType.Byond, + version + }; this.setState({ - latestVersion: version, - selectedVersion: version, + latestByondVersion: engineVersion, + selectedByondVersion: engineVersion, loading: false }); }) @@ -164,6 +182,30 @@ class Byond extends React.Component { loading: false }); }); + + await this.loadVersions(); + + const odLatestCommit = await odGetPromise; + if (odLatestCommit.code === StatusCode.ERROR) { + this.addError(odLatestCommit.error); + return; + } + + const newVer = { + engine: EngineType.OpenDream, + sourceSHA: odLatestCommit.payload + }; + + this.setState(prev => { + return { + latestODVersion: newVer, + selectedODVersion: + this.makeUniqueStringForVersion(prev.latestODVersion) == + this.makeUniqueStringForVersion(prev.selectedODVersion ?? prev.latestODVersion) + ? newVer + : prev.selectedODVersion + }; + }); } public render(): React.ReactNode { @@ -171,42 +213,32 @@ class Byond extends React.Component { return ; } - const canSeeVersions = hasByondRight( + const canSeeVersions = hasEngineRight( this.context.instancePermissionSet, - ByondRights.ListInstalled + EngineRights.ListInstalled ); - const canSeeCurrent = hasByondRight( + const canSeeCurrent = hasEngineRight( this.context.instancePermissionSet, - ByondRights.ReadActive + EngineRights.ReadActive ); - const canInstallCustom = hasByondRight( + const canInstallAndSwitchByond = hasEngineRight( this.context.instancePermissionSet, - ByondRights.InstallCustomVersion + EngineRights.InstallOfficialOrChangeActiveByondVersion ); - const canInstallAndSwitch = hasByondRight( + const canInstallAndSwitchOD = hasEngineRight( this.context.instancePermissionSet, - ByondRights.InstallOfficialOrChangeActiveVersion + EngineRights.InstallOfficialOrChangeActiveOpenDreamVersion ); - const canDelete = hasByondRight( + const canDelete = hasEngineRight( this.context.instancePermissionSet, - ByondRights.DeleteInstall + EngineRights.DeleteInstall ); - const tooltip = (innerid?: string) => { - if (!innerid) return ; - - return ( - - - - ); - }; - return (
- +

- +

{this.state.errors.map((err, index) => { if (!err) return; @@ -229,29 +261,45 @@ class Byond extends React.Component { {canSeeVersions ? ( <> {!canSeeCurrent ? ( - + ) : null}
- {this.state.versions.map(version => { + {this.state.versions.map(item => { // noinspection JSBitwiseOperatorUsage return ( - {canInstallAndSwitch || canSeeCurrent ? ( + key={this.makeUniqueStringForVersion(item.engineVersion)}> + {canInstallAndSwitchByond || canSeeCurrent ? ( { await this.switchVersion( - version.version!, + item.engineVersion, false ); }} @@ -260,11 +308,15 @@ class Byond extends React.Component { ) : null}
+ ); } + private renderODInstall(): React.ReactNode { + const canInstallCustomOD = hasEngineRight( + this.context.instancePermissionSet, + EngineRights.InstallCustomOpenDreamVersion + ); + const canInstallAndSwitchOD = hasEngineRight( + this.context.instancePermissionSet, + EngineRights.InstallOfficialOrChangeActiveOpenDreamVersion + ); + return ( + +

+ +

+ + { + this.setState({ + selectedODVersion: { + engine: EngineType.OpenDream, + sourceSHA: e.target.value + } + }); + }} + /> + + + + + + +
+ + + ) + } + accept=".zip" + onChange={(e: ChangeEvent) => { + this.setState({ + customFile: e.target.files ? e.target.files[0] : null + }); + }} + /> + +
+
+ ); + } + + private makeUniqueStringForVersion(engineVersion?: EngineVersion): string { + if (!engineVersion) { + return "null-version"; + } + + return `${engineVersion.engine}-${engineVersion.version ?? "null"}-${ + engineVersion.sourceSHA ?? "null" + }-${engineVersion.customIteration ?? "null"}`; + } + + public static friendlyVersion(engineVersion: EngineVersion): string { + let baseVersion: string; + switch (engineVersion.engine) { + case EngineType.Byond: + baseVersion = engineVersion.version!; + if (baseVersion.endsWith(".0")) { + baseVersion = baseVersion.substring(0, baseVersion.length - 2); + } + break; + case EngineType.OpenDream: + baseVersion = `OD-${engineVersion.sourceSHA!.substring(0, 7)}`; + break; + default: + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + throw new Error(`Unknown engine type: ${engineVersion.engine}`); + } + + if (engineVersion.customIteration) { + return `${baseVersion} (${engineVersion.customIteration})`; + } + + return baseVersion; + } } -Byond.contextType = InstanceEditContext; -export default Byond; +Engine.contextType = InstanceEditContext; +export default Engine; diff --git a/src/components/views/Instance/Edit/InstancePermissions.tsx b/src/components/views/Instance/Edit/InstancePermissions.tsx index 6b1daee6..e02dc482 100644 --- a/src/components/views/Instance/Edit/InstancePermissions.tsx +++ b/src/components/views/Instance/Edit/InstancePermissions.tsx @@ -9,11 +9,11 @@ import { RouteComponentProps, withRouter } from "react-router-dom"; import { AdministrationRights, - ByondRights, ChatBotRights, ConfigurationRights, DreamDaemonRights, DreamMakerRights, + EngineRights, InstanceManagerRights, InstancePermissionSetResponse, InstancePermissionSetRights, @@ -62,7 +62,7 @@ interface IState { currentPermissions: InstancePermissionSetResponse | null; permsinstancepermissionset: Record; permsrepository: Record; - permsbyond: Record; + permsengine: Record; permsdreammaker: Record; permsdreamdaemon: Record; permschatbots: Record; @@ -89,7 +89,7 @@ class InstancePermissions extends React.Component { permissionSetId: 0, instancePermissionSetRights: 0, repositoryRights: 0, - byondRights: 0, + engineRights: 0, dreamMakerRights: 0, dreamDaemonRights: 0, chatBotRights: 0, @@ -99,7 +99,7 @@ class InstancePermissions extends React.Component { selectedPermissionSetId: 0, permsinstancepermissionset: {}, permsrepository: {}, - permsbyond: {}, + permsengine: {}, permsdreammaker: {}, permsdreamdaemon: {}, permschatbots: {}, @@ -161,7 +161,7 @@ class InstancePermissions extends React.Component { "permsinstancepermissionset" ); loadEnum(RepositoryRights, "repositoryRights", "permsrepository"); - loadEnum(ByondRights, "byondRights", "permsbyond"); + loadEnum(EngineRights, "engineRights", "permsengine"); loadEnum(DreamMakerRights, "dreamMakerRights", "permsdreammaker"); loadEnum(DreamDaemonRights, "dreamDaemonRights", "permsdreamdaemon"); loadEnum(ChatBotRights, "chatBotRights", "permschatbots"); @@ -613,8 +613,8 @@ class InstancePermissions extends React.Component { title={}> {this.renderPerms("permsrepository", "repository", canEdit)} - }> - {this.renderPerms("permsbyond", "byond", canEdit)} + }> + {this.renderPerms("permsengine", "engine", canEdit)} { enumname: | "permsinstancepermissionset" | "permsrepository" - | "permsbyond" + | "permsengine" | "permsdreammaker" | "permsdreamdaemon" | "permschatbots" @@ -725,8 +725,8 @@ class InstancePermissions extends React.Component { case "permsrepository": rightsType = "RepositoryRights"; break; - case "permsbyond": - rightsType = "ByondRights"; + case "permsengine": + rightsType = "EngineRights"; break; case "permsdreammaker": rightsType = "DreamMakerRights"; @@ -744,7 +744,7 @@ class InstancePermissions extends React.Component { const newset = Object.assign(Object.assign({}, this.state.currentPermissions), { [rightsType]: bitflag - } as { InstancePermissionSetRights: InstancePermissionSetRights } | { RepositoryRights: RepositoryRights } | { ByondRights: ByondRights } | { DreamMakerRights: DreamMakerRights } | { DreamDaemonRights: DreamDaemonRights } | { ChatBotRights: ChatBotRights } | { ConfigurationRights: ConfigurationRights }); + } as { InstancePermissionSetRights: InstancePermissionSetRights } | { RepositoryRights: RepositoryRights } | { EngineRights: EngineRights } | { DreamMakerRights: DreamMakerRights } | { DreamDaemonRights: DreamDaemonRights } | { ChatBotRights: ChatBotRights } | { ConfigurationRights: ConfigurationRights }); const response = await InstancePermissionSetClient.updateInstancePermissionSet( this.context.instance.id, diff --git a/src/components/views/Instance/InstanceEdit.tsx b/src/components/views/Instance/InstanceEdit.tsx index 1041b138..83b567d5 100644 --- a/src/components/views/Instance/InstanceEdit.tsx +++ b/src/components/views/Instance/InstanceEdit.tsx @@ -1,4 +1,5 @@ import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { faGamepad } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React, { ComponentType } from "react"; import Card from "react-bootstrap/Card"; @@ -8,11 +9,11 @@ import { FormattedMessage } from "react-intl"; import { RouteComponentProps, withRouter } from "react-router"; import { - ByondRights, ChatBotRights, ConfigurationRights, DreamDaemonRights, DreamMakerRights, + EngineRights, InstancePermissionSetResponse, RepositoryRights } from "../../../ApiClient/generatedcode/generated"; @@ -30,10 +31,10 @@ import { AppRoutes, RouteData } from "../../../utils/routes"; import AccessDenied from "../../utils/AccessDenied"; import Loading from "../../utils/Loading"; import WIPNotice from "../../utils/WIPNotice"; -import Byond from "./Edit/Byond"; import ChatBots from "./Edit/ChatBots"; import Config from "./Edit/Config"; import { Deployment } from "./Edit/Deployment"; +import Engine from "./Edit/Engine"; import Files from "./Edit/Files"; import InstancePermissions from "./Edit/InstancePermissions"; import JobHistory from "./Edit/JobHistory"; @@ -46,11 +47,13 @@ type IState = Omit & { instanceid: number; }; -const minimumByondPerms = - ByondRights.ReadActive | - ByondRights.ListInstalled | - ByondRights.InstallOfficialOrChangeActiveVersion | - ByondRights.InstallCustomVersion; +const minimumEnginePerms = + EngineRights.ReadActive | + EngineRights.ListInstalled | + EngineRights.InstallOfficialOrChangeActiveByondVersion | + EngineRights.InstallCustomByondVersion | + EngineRights.InstallOfficialOrChangeActiveOpenDreamVersion | + EngineRights.InstallCustomOpenDreamVersion; const minimumServerPerms = DreamDaemonRights.SetPort | @@ -117,10 +120,10 @@ class InstanceEdit extends React.Component { Repository ], [ - "byond", - "list-ul", - instancePermissionSet => !!(instancePermissionSet.byondRights & minimumByondPerms), - Byond + "engine", + faGamepad, + instancePermissionSet => !!(instancePermissionSet.engineRights & minimumEnginePerms), + Engine ], [ "deployment", diff --git a/src/definitions/globals.d.ts b/src/definitions/globals.d.ts index 0381f29c..cbfd2e5a 100644 --- a/src/definitions/globals.d.ts +++ b/src/definitions/globals.d.ts @@ -11,15 +11,3 @@ declare global { publicPath: string; } } - -/* -AdminClient: AdminClient; - ByondClient: ByondClient; - InstanceClient: InstanceClient; - InstancePermissionSetClient: InstancePermissionSetClient; - JobsClient: JobsClient; - ServerClient: ServerClient; - TransferClient: TransferClient; - UserClient: UserClient; - UserGroupClient: UserGroupClient; - */ diff --git a/src/translations/locales/en.json b/src/translations/locales/en.json index 04c7206e..cb748426 100644 --- a/src/translations/locales/en.json +++ b/src/translations/locales/en.json @@ -87,7 +87,7 @@ "error.bad_tgs_yml_version": "Incorrect .tgs.yml version. Only version 1 is supported.", "error.bad_yml": "Malformed .yml.", "error.bad_channels_json": "Malformed channels JSON.", - "error.no_byond_version": "The target BYOND version does not exist on the server.", + "error.no_engine_version": "The target engine version does not exist on the server.", "error.bad_hub_connection": "Lost connection to the SignalR hub.", "generic.save": "Save", "generic.savetab": "Save Tab", @@ -223,7 +223,7 @@ "view.instanceedit.tabs.repository": "Repository", "view.instanceedit.tabs.deployment": "Deployment", "view.instanceedit.tabs.dreamdaemon": "Server", - "view.instanceedit.tabs.byond": "BYOND version", + "view.instanceedit.tabs.engine": "Engine", "view.instanceedit.tabs.chatbots": "Chat Bots", "view.instanceedit.tabs.files": "Files & Scripts", "view.instanceedit.tabs.users": "Permissions", @@ -273,14 +273,15 @@ "view.instance.config.instancesettings": "Instance Settings", "view.instance.config.instanceusers": "Instance Users", "view.instance.config.chatbots": "Chat Bots", - "view.instance.byond": "Version Selector", - "view.instance.byond.add": "Install new BYOND version", - "view.instance.byond.upload": "Upload custom version", - "view.instance.byond.custom": "Uploaded from zip file", - "view.instance.byond.current_and_list_denied": "This user does not have the permission to access information about BYOND versions", - "view.instance.byond.list_denied": "This user does not have the permission to list all installed BYOND versions", - "view.instance.byond.current_denied": "This user does not have the permission to see the active BYOND version", - "view.instance.byond.current_version": "Active Version: {version}", + "view.instance.engine": "Version Selector", + "view.instance.engine.add_byond": "Install new BYOND version", + "view.instance.engine.add_od": "Install new OpenDream version", + "view.instance.engine.upload": "Upload custom version", + "view.instance.engine.custom": "Uploaded from zip file", + "view.instance.engine.current_and_list_denied": "This user does not have the permission to access information about BYOND versions", + "view.instance.engine.list_denied": "This user does not have the permission to list all installed BYOND versions", + "view.instance.engine.current_denied": "This user does not have the permission to see the active BYOND version", + "view.instance.engine.current_version": "Active Version: {version}", "view.instance.chat": "Chat Bots", "view.instance.chat.create": "Add Bot", "view.instance.chat.create.invalid.discord": "Invalid Discord channel ID!", @@ -523,18 +524,22 @@ "perms.repository.cancelclone.desc": "Allows cancelling active repository clone jobs.", "perms.repository.changesubmoduleupdate": "Change Submodule Update", "perms.repository.changesubmoduleupdate.desc": "Allows changing the setting to update submodules with branches.", - "perms.byond": "Byond", - "perms.byond.readactive": "Read Active Version", - "perms.byond.readactive.desc": "Allows reading the active BYOND version.", - "perms.byond.listinstalled": "List Installed Versions", - "perms.byond.listinstalled.desc": "Allows reading all installed BYOND versions.", - "perms.byond.installofficialorchangeactiveversion": "Activate/Install BYOND Version", - "perms.byond.installofficialorchangeactiveversion.desc": "Allows installation and activation of BYOND versions downloaded from the official website. Pre-installed custom versions may also be activated", - "perms.byond.cancelinstall": "Cancel Install Job", - "perms.byond.cancelinstall.desc": "Allows cancelling BYOND install jobs.", - "perms.byond.installcustomversion": "Install Custom BYOND Version", - "perms.byond.installcustomversion.desc": "Allows installing a BYOND version uploaded from a zip file.", - "perms.byond.deleteinstall": "Delete BYOND Version", + "perms.engine": "Engine", + "perms.engine.readactive": "Read Active Version", + "perms.engine.readactive.desc": "Allows reading the active engine version.", + "perms.engine.listinstalled": "List Installed Versions", + "perms.engine.listinstalled.desc": "Allows reading all installed engine versions.", + "perms.engine.installofficialorchangeactivebyondversion": "Activate/Install BYOND Version", + "perms.engine.installofficialorchangeactivebyondversion.desc": "Allows installation and activation of BYOND versions downloaded from the official website. Pre-installed custom versions may also be activated", + "perms.engine.installofficialorchangeactiveopendreamversion": "Activate/Install OpenDream Version", + "perms.engine.installofficialorchangeactiveopendreamversion.desc": "Allows installation and activation of OpenDream versions downloaded from the configured git. Pre-installed custom versions may also be activated", + "perms.engine.cancelinstall": "Cancel Install Job", + "perms.engine.cancelinstall.desc": "Allows cancelling install jobs.", + "perms.engine.installcustombyondversion": "Install Custom BYOND Version", + "perms.engine.installcustombyondversion.desc": "Allows installing a BYOND version uploaded from a zip file.", + "perms.engine.installcustomopendreamversion": "Install Custom OpenDream Version", + "perms.engine.installcustomopendreamversion.desc": "Allows installing an OpenDream version uploaded from a zip file.", + "perms.engine.deleteinstall": "Delete Engine Version", "perms.dreammaker": "Deployment", "perms.dreammaker.read": "Read Deployment Settings", "perms.dreammaker.read.desc": "Allows reading information about the deployment settings.", diff --git a/src/utils/GithubClient.ts b/src/utils/GithubClient.ts index 1720d2d0..32bcf68d 100644 --- a/src/utils/GithubClient.ts +++ b/src/utils/GithubClient.ts @@ -116,6 +116,36 @@ const e = new (class GithubClient extends TypedEmitter { }); } + public async getLatestDefaultCommit( + owner: string, + repo: string + ): Promise> { + try { + const repoData = await this.apiClient.repos.get({ + owner, + repo + }); + + const branch = await this.apiClient.repos.getBranch({ + owner, + repo, + branch: repoData.data.default_branch + }); + + return new InternalStatus({ + code: StatusCode.OK, + payload: branch.data.commit.sha + }); + } catch (e) { + return new InternalStatus({ + code: StatusCode.ERROR, + error: new InternalError(ErrorCode.GITHUB_FAIL, { + jsError: e as RequestError + }) + }); + } + } + public async getVersions({ owner, repo, diff --git a/src/utils/icolibrary.ts b/src/utils/icolibrary.ts index 8c031150..c44ef378 100644 --- a/src/utils/icolibrary.ts +++ b/src/utils/icolibrary.ts @@ -12,6 +12,7 @@ import { faFileAlt, faFolderMinus, faFolderPlus, + faGamepad, faHashtag, faMinus, faUnlock, @@ -98,6 +99,7 @@ export default function (): void { faClipboard, faArrowLeft, faAngleRight, - faUpload + faUpload, + faGamepad ); } diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 53363f14..8b93fa8f 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -2,11 +2,11 @@ import { pathToRegexp } from "path-to-regexp"; import { AdministrationRights, - ByondRights, ChatBotRights, ConfigurationRights, DreamDaemonRights, DreamMakerRights, + EngineRights, InstanceManagerRights, InstancePermissionSetResponse, InstancePermissionSetRights, @@ -64,8 +64,11 @@ function hasInstanceManagerRight( return bitflagIsTrue(permissionSet.instanceManagerRights, right); } -function hasByondRight(permissionSet: InstancePermissionSetResponse, right: ByondRights): boolean { - return bitflagIsTrue(permissionSet.byondRights, right); +function hasEngineRight( + permissionSet: InstancePermissionSetResponse, + right: EngineRights +): boolean { + return bitflagIsTrue(permissionSet.engineRights, right); } function hasChatBotRight( @@ -124,7 +127,7 @@ export { resolvePermissionSet, bitflagIsTrue, hasAdminRight, - hasByondRight, + hasEngineRight, hasConfigRight, hasRepoRight, hasChatBotRight, diff --git a/yarn.lock b/yarn.lock index f5d5bf8a..39c0bffd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6210,6 +6210,13 @@ __metadata: languageName: node linkType: hard +"jwt-decode@npm:^4.0.0": + version: 4.0.0 + resolution: "jwt-decode@npm:4.0.0" + checksum: 390e2edcb31a92e86c8cbdd1edeea4c0d62acd371f8a8f0a8878e499390c0ecf4c658b365c4e941e4ef37d0170e4ca650aaa49f99a45c0b9695a235b210154b0 + languageName: node + linkType: hard + "kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" @@ -9243,6 +9250,7 @@ __metadata: html-webpack-plugin: ^5.5.0 https-browserify: ^1.0.0 jquery: ^3.5.1 + jwt-decode: ^4.0.0 patch-package: ^6.4.7 path-to-regexp: ^6.2.0 popper.js: ^1.16.1