diff --git a/app/Http/Controllers/Api/Client/Servers/StartupController.php b/app/Http/Controllers/Api/Client/Servers/StartupController.php
new file mode 100644
index 000000000..6eb1df0ad
--- /dev/null
+++ b/app/Http/Controllers/Api/Client/Servers/StartupController.php
@@ -0,0 +1,81 @@
+service = $service;
+ $this->repository = $repository;
+ }
+
+ /**
+ * Updates a single variable for a server.
+ *
+ * @param \Pterodactyl\Http\Requests\Api\Client\Servers\Startup\UpdateStartupVariableRequest $request
+ * @param \Pterodactyl\Models\Server $server
+ * @return array
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ * @throws \Pterodactyl\Exceptions\Model\DataValidationException
+ * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
+ */
+ public function update(UpdateStartupVariableRequest $request, Server $server)
+ {
+ /** @var \Pterodactyl\Models\EggVariable $variable */
+ $variable = $server->variables()->where('env_variable', $request->input('key'))->first();
+
+ if (is_null($variable) || !$variable->user_viewable || !$variable->user_editable) {
+ throw new BadRequestHttpException(
+ "The environment variable you are trying to edit [\"{$request->input('key')}\"] does not exist."
+ );
+ }
+
+ // Revalidate the variable value using the egg variable specific validation rules for it.
+ $this->validate($request, ['value' => $variable->rules]);
+
+ $this->repository->updateOrCreate([
+ 'server_id' => $server->id,
+ 'variable_id' => $variable->id,
+ ], [
+ 'variable_value' => $request->input('value'),
+ ]);
+
+ $variable = $variable->refresh();
+ $variable->server_value = $request->input('value');
+
+ return $this->fractal->item($variable)
+ ->transformWith($this->getTransformer(EggVariableTransformer::class))
+ ->toArray();
+ }
+}
diff --git a/app/Http/Requests/Api/Client/Servers/Startup/UpdateStartupVariableRequest.php b/app/Http/Requests/Api/Client/Servers/Startup/UpdateStartupVariableRequest.php
new file mode 100644
index 000000000..63005c78b
--- /dev/null
+++ b/app/Http/Requests/Api/Client/Servers/Startup/UpdateStartupVariableRequest.php
@@ -0,0 +1,30 @@
+ 'required|string',
+ 'value' => 'present|string',
+ ];
+ }
+}
diff --git a/app/Models/Permission.php b/app/Models/Permission.php
index af3dc5cf9..a7eb2709b 100644
--- a/app/Models/Permission.php
+++ b/app/Models/Permission.php
@@ -55,6 +55,9 @@ class Permission extends Model
const ACTION_FILE_ARCHIVE = 'file.archive';
const ACTION_FILE_SFTP = 'file.sftp';
+ const ACTION_STARTUP_READ = 'startup.read';
+ const ACTION_STARTUP_UPDATE = 'startup.update';
+
const ACTION_SETTINGS_RENAME = 'settings.rename';
const ACTION_SETTINGS_REINSTALL = 'settings.reinstall';
@@ -169,8 +172,8 @@ class Permission extends Model
'startup' => [
'description' => 'Permissions that control a user\'s ability to view this server\'s startup parameters.',
'keys' => [
- 'read' => '',
- 'update' => '',
+ 'read' => 'Allows a user to view the startup variables for a server.',
+ 'update' => 'Allows a user to modify the startup variables for the server.',
],
],
diff --git a/resources/scripts/.eslintrc.yml b/resources/scripts/.eslintrc.yml
index 0e22c8f66..b18f90af9 100644
--- a/resources/scripts/.eslintrc.yml
+++ b/resources/scripts/.eslintrc.yml
@@ -39,6 +39,8 @@ rules:
comma-dangle:
- warn
- always-multiline
+ spaced-comment:
+ - warn
array-bracket-spacing:
- warn
- always
diff --git a/resources/scripts/api/server/getServer.ts b/resources/scripts/api/server/getServer.ts
index 36dcffda9..278b21e17 100644
--- a/resources/scripts/api/server/getServer.ts
+++ b/resources/scripts/api/server/getServer.ts
@@ -1,5 +1,6 @@
import http, { FractalResponseData, FractalResponseList } from '@/api/http';
-import { rawDataToServerAllocation } from '@/api/transformers';
+import { rawDataToServerAllocation, rawDataToServerEggVariable } from '@/api/transformers';
+import { ServerEggVariable } from '@/api/server/types';
export interface Allocation {
id: number;
@@ -21,7 +22,6 @@ export interface Server {
};
invocation: string;
description: string;
- allocations: Allocation[];
limits: {
memory: number;
swap: number;
@@ -37,6 +37,8 @@ export interface Server {
};
isSuspended: boolean;
isInstalling: boolean;
+ variables: ServerEggVariable[];
+ allocations: Allocation[];
}
export const rawDataToServerObject = ({ attributes: data }: FractalResponseData): Server => ({
@@ -54,6 +56,7 @@ export const rawDataToServerObject = ({ attributes: data }: FractalResponseData)
featureLimits: { ...data.feature_limits },
isSuspended: data.is_suspended,
isInstalling: data.is_installing,
+ variables: ((data.relationships?.variables as FractalResponseList | undefined)?.data || []).map(rawDataToServerEggVariable),
allocations: ((data.relationships?.allocations as FractalResponseList | undefined)?.data || []).map(rawDataToServerAllocation),
});
diff --git a/resources/scripts/api/server/types.d.ts b/resources/scripts/api/server/types.d.ts
index bcdd7416d..e11a39c45 100644
--- a/resources/scripts/api/server/types.d.ts
+++ b/resources/scripts/api/server/types.d.ts
@@ -8,3 +8,13 @@ export interface ServerBackup {
createdAt: Date;
completedAt: Date | null;
}
+
+export interface ServerEggVariable {
+ name: string;
+ description: string;
+ envVariable: string;
+ defaultValue: string;
+ serverValue: string;
+ isEditable: boolean;
+ rules: string[];
+}
diff --git a/resources/scripts/api/server/updateStartupVariable.ts b/resources/scripts/api/server/updateStartupVariable.ts
new file mode 100644
index 000000000..88231eccc
--- /dev/null
+++ b/resources/scripts/api/server/updateStartupVariable.ts
@@ -0,0 +1,9 @@
+import http from '@/api/http';
+import { ServerEggVariable } from '@/api/server/types';
+import { rawDataToServerEggVariable } from '@/api/transformers';
+
+export default async (uuid: string, key: string, value: string): Promise
+ {variable.description} +
+