Skip to content

Commit 9b7af02

Browse files
committed
Add activity logging to most of the endpoints
1 parent 287fd60 commit 9b7af02

File tree

11 files changed

+171
-31
lines changed

11 files changed

+171
-31
lines changed

app/Facades/Activity.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* @method static ActivityLogService property(string|array $key, mixed $value = null)
1717
* @method static \Pterodactyl\Models\ActivityLog log(string $description = null)
1818
* @method static ActivityLogService clone()
19+
* @method static void reset()
1920
* @method static mixed transaction(\Closure $callback)
2021
*/
2122
class Activity extends Facade

app/Http/Controllers/Api/Client/Servers/DatabaseController.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Http\Response;
66
use Pterodactyl\Models\Server;
77
use Pterodactyl\Models\Database;
8+
use Pterodactyl\Facades\Activity;
89
use Pterodactyl\Repositories\Eloquent\DatabaseRepository;
910
use Pterodactyl\Services\Databases\DatabasePasswordService;
1011
use Pterodactyl\Transformers\Api\Client\DatabaseTransformer;
@@ -76,6 +77,11 @@ public function store(StoreDatabaseRequest $request, Server $server): array
7677
{
7778
$database = $this->deployDatabaseService->handle($server, $request->validated());
7879

80+
Activity::event('server:database.create')
81+
->subject($database)
82+
->property('name', $database->database)
83+
->log();
84+
7985
return $this->fractal->item($database)
8086
->parseIncludes(['password'])
8187
->transformWith($this->getTransformer(DatabaseTransformer::class))
@@ -95,6 +101,8 @@ public function rotatePassword(RotatePasswordRequest $request, Server $server, D
95101
$this->passwordService->handle($database);
96102
$database->refresh();
97103

104+
Activity::event('server:database.rotate-password')->subject($database)->log();
105+
98106
return $this->fractal->item($database)
99107
->parseIncludes(['password'])
100108
->transformWith($this->getTransformer(DatabaseTransformer::class))
@@ -110,6 +118,11 @@ public function delete(DeleteDatabaseRequest $request, Server $server, Database
110118
{
111119
$this->managementService->delete($database);
112120

121+
Activity::event('server:database.delete')
122+
->subject($database)
123+
->property('name', $database->database)
124+
->log();
125+
113126
return Response::create('', Response::HTTP_NO_CONTENT);
114127
}
115128
}

app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Pterodactyl\Models\Server;
66
use Illuminate\Http\JsonResponse;
7+
use Pterodactyl\Facades\Activity;
78
use Pterodactyl\Models\Allocation;
89
use Pterodactyl\Exceptions\DisplayException;
910
use Pterodactyl\Repositories\Eloquent\ServerRepository;
@@ -68,9 +69,16 @@ public function index(GetNetworkRequest $request, Server $server): array
6869
*/
6970
public function update(UpdateAllocationRequest $request, Server $server, Allocation $allocation): array
7071
{
71-
$allocation = $this->repository->update($allocation->id, [
72-
'notes' => $request->input('notes'),
73-
]);
72+
$original = $allocation->notes;
73+
74+
$allocation->forceFill(['notes' => $request->input('notes')])->save();
75+
76+
if ($original !== $allocation->notes) {
77+
Activity::event('server:allocation.notes')
78+
->subject($allocation)
79+
->property(['allocation' => $allocation->toString(), 'old' => $original, 'new' => $allocation->notes])
80+
->log();
81+
}
7482

7583
return $this->fractal->item($allocation)
7684
->transformWith($this->getTransformer(AllocationTransformer::class))
@@ -87,6 +95,11 @@ public function setPrimary(SetPrimaryAllocationRequest $request, Server $server,
8795
{
8896
$this->serverRepository->update($server->id, ['allocation_id' => $allocation->id]);
8997

98+
Activity::event('server:allocation.primary')
99+
->subject($allocation)
100+
->property('allocation', $allocation->toString())
101+
->log();
102+
90103
return $this->fractal->item($allocation)
91104
->transformWith($this->getTransformer(AllocationTransformer::class))
92105
->toArray();
@@ -106,6 +119,11 @@ public function store(NewAllocationRequest $request, Server $server): array
106119

107120
$allocation = $this->assignableAllocationService->handle($server);
108121

122+
Activity::event('server:allocation.create')
123+
->subject($allocation)
124+
->property('allocation', $allocation->toString())
125+
->log();
126+
109127
return $this->fractal->item($allocation)
110128
->transformWith($this->getTransformer(AllocationTransformer::class))
111129
->toArray();
@@ -135,6 +153,11 @@ public function delete(DeleteAllocationRequest $request, Server $server, Allocat
135153
'server_id' => null,
136154
]);
137155

156+
Activity::event('server:allocation.delete')
157+
->subject($allocation)
158+
->property('allocation', $allocation->toString())
159+
->log();
160+
138161
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
139162
}
140163
}

app/Http/Controllers/Api/Client/Servers/ScheduleController.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Pterodactyl\Models\Server;
1010
use Pterodactyl\Models\Schedule;
1111
use Illuminate\Http\JsonResponse;
12+
use Pterodactyl\Facades\Activity;
1213
use Pterodactyl\Helpers\Utilities;
1314
use Pterodactyl\Exceptions\DisplayException;
1415
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
@@ -83,6 +84,11 @@ public function store(StoreScheduleRequest $request, Server $server)
8384
'next_run_at' => $this->getNextRunAt($request),
8485
]);
8586

87+
Activity::event('server:schedule.create')
88+
->subject($model)
89+
->property('name', $model->name)
90+
->log();
91+
8692
return $this->fractal->item($model)
8793
->transformWith($this->getTransformer(ScheduleTransformer::class))
8894
->toArray();
@@ -141,6 +147,11 @@ public function update(UpdateScheduleRequest $request, Server $server, Schedule
141147

142148
$this->repository->update($schedule->id, $data);
143149

150+
Activity::event('server:schedule.update')
151+
->subject($schedule)
152+
->property(['name' => $schedule->name, 'active' => $active])
153+
->log();
154+
144155
return $this->fractal->item($schedule->refresh())
145156
->transformWith($this->getTransformer(ScheduleTransformer::class))
146157
->toArray();
@@ -158,6 +169,8 @@ public function execute(TriggerScheduleRequest $request, Server $server, Schedul
158169
{
159170
$this->service->handle($schedule, true);
160171

172+
Activity::event('server:schedule.execute')->subject($schedule)->property('name', $schedule->name)->log();
173+
161174
return new JsonResponse([], JsonResponse::HTTP_ACCEPTED);
162175
}
163176

@@ -170,6 +183,8 @@ public function delete(DeleteScheduleRequest $request, Server $server, Schedule
170183
{
171184
$this->repository->delete($schedule->id);
172185

186+
Activity::event('server:schedule.delete')->subject($schedule)->property('name', $schedule->name)->log();
187+
173188
return new JsonResponse([], Response::HTTP_NO_CONTENT);
174189
}
175190

app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Pterodactyl\Models\Server;
88
use Pterodactyl\Models\Schedule;
99
use Illuminate\Http\JsonResponse;
10+
use Pterodactyl\Facades\Activity;
1011
use Pterodactyl\Models\Permission;
1112
use Pterodactyl\Repositories\Eloquent\TaskRepository;
1213
use Pterodactyl\Exceptions\Http\HttpForbiddenException;
@@ -67,6 +68,11 @@ public function store(StoreTaskRequest $request, Server $server, Schedule $sched
6768
'continue_on_failure' => (bool) $request->input('continue_on_failure'),
6869
]);
6970

71+
Activity::event('server:task.create')
72+
->subject($schedule, $task)
73+
->property(['name' => $schedule->name, 'action' => $task->action, 'payload' => $task->payload])
74+
->log();
75+
7076
return $this->fractal->item($task)
7177
->transformWith($this->getTransformer(TaskTransformer::class))
7278
->toArray();
@@ -98,6 +104,11 @@ public function update(StoreTaskRequest $request, Server $server, Schedule $sche
98104
'continue_on_failure' => (bool) $request->input('continue_on_failure'),
99105
]);
100106

107+
Activity::event('server:task.update')
108+
->subject($schedule, $task)
109+
->property(['name' => $schedule->name, 'action' => $task->action, 'payload' => $task->payload])
110+
->log();
111+
101112
return $this->fractal->item($task->refresh())
102113
->transformWith($this->getTransformer(TaskTransformer::class))
103114
->toArray();
@@ -127,6 +138,8 @@ public function delete(ClientApiRequest $request, Server $server, Schedule $sche
127138

128139
$task->delete();
129140

141+
Activity::event('server:task.delete')->subject($schedule, $task)->property('name', $schedule->name)->log();
142+
130143
return new JsonResponse(null, Response::HTTP_NO_CONTENT);
131144
}
132145
}

app/Http/Controllers/Api/Client/Servers/SettingsController.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Http\Response;
66
use Pterodactyl\Models\Server;
77
use Illuminate\Http\JsonResponse;
8+
use Pterodactyl\Facades\Activity;
89
use Pterodactyl\Repositories\Eloquent\ServerRepository;
910
use Pterodactyl\Services\Servers\ReinstallServerService;
1011
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
@@ -52,6 +53,12 @@ public function rename(RenameServerRequest $request, Server $server)
5253
'name' => $request->input('name'),
5354
]);
5455

56+
if ($server->name !== $request->input('name')) {
57+
Activity::event('server:settings.rename')
58+
->property(['old' => $server->name, 'new' => $request->input('name')])
59+
->log();
60+
}
61+
5562
return new JsonResponse([], Response::HTTP_NO_CONTENT);
5663
}
5764

@@ -66,6 +73,8 @@ public function reinstall(ReinstallServerRequest $request, Server $server)
6673
{
6774
$this->reinstallServerService->handle($server);
6875

76+
Activity::event('server:reinstall')->log();
77+
6978
return new JsonResponse([], Response::HTTP_ACCEPTED);
7079
}
7180

@@ -82,8 +91,15 @@ public function dockerImage(SetDockerImageRequest $request, Server $server)
8291
throw new BadRequestHttpException('This server\'s Docker image has been manually set by an administrator and cannot be updated.');
8392
}
8493

94+
$original = $server->image;
8595
$server->forceFill(['image' => $request->input('docker_image')])->saveOrFail();
8696

97+
if ($original !== $server->image) {
98+
Activity::event('server:startup.image')
99+
->property(['old' => $original, 'new' => $request->input('docker_image')])
100+
->log();
101+
}
102+
87103
return new JsonResponse([], Response::HTTP_NO_CONTENT);
88104
}
89105
}

app/Http/Controllers/Api/Client/Servers/StartupController.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
44

55
use Pterodactyl\Models\Server;
6+
use Pterodactyl\Facades\Activity;
67
use Pterodactyl\Services\Servers\StartupCommandService;
78
use Pterodactyl\Services\Servers\VariableValidatorService;
89
use Pterodactyl\Repositories\Eloquent\ServerVariableRepository;
@@ -75,6 +76,7 @@ public function update(UpdateStartupVariableRequest $request, Server $server)
7576
{
7677
/** @var \Pterodactyl\Models\EggVariable $variable */
7778
$variable = $server->variables()->where('env_variable', $request->input('key'))->first();
79+
$original = $variable->server_value;
7880

7981
if (is_null($variable) || !$variable->user_viewable) {
8082
throw new BadRequestHttpException('The environment variable you are trying to edit does not exist.');
@@ -97,6 +99,17 @@ public function update(UpdateStartupVariableRequest $request, Server $server)
9799

98100
$startup = $this->startupCommandService->handle($server, false);
99101

102+
if ($variable->env_variable !== $request->input('value')) {
103+
Activity::event('server:startup.edit')
104+
->subject($variable)
105+
->property([
106+
'variable' => $variable->env_variable,
107+
'old' => $original,
108+
'new' => $request->input('value'),
109+
])
110+
->log();
111+
}
112+
100113
return $this->fractal->item($variable)
101114
->transformWith($this->getTransformer(EggVariableTransformer::class))
102115
->addMeta([

app/Http/Controllers/Api/Client/Servers/SubuserController.php

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Http\Request;
66
use Pterodactyl\Models\Server;
77
use Illuminate\Http\JsonResponse;
8+
use Pterodactyl\Facades\Activity;
89
use Pterodactyl\Models\Permission;
910
use Illuminate\Support\Facades\Log;
1011
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
@@ -94,6 +95,11 @@ public function store(StoreSubuserRequest $request, Server $server)
9495
$this->getDefaultPermissions($request)
9596
);
9697

98+
Activity::event('server:subuser.create')
99+
->subject($response->user)
100+
->property(['email' => $request->input('email'), 'permissions' => $this->getDefaultPermissions($request)])
101+
->log();
102+
97103
return $this->fractal->item($response)
98104
->transformWith($this->getTransformer(SubuserTransformer::class))
99105
->toArray();
@@ -116,22 +122,37 @@ public function update(UpdateSubuserRequest $request, Server $server): array
116122
sort($permissions);
117123
sort($current);
118124

125+
$log = Activity::event('server:subuser.update')
126+
->subject($subuser->user)
127+
->property([
128+
'email' => $subuser->user->email,
129+
'old' => $current,
130+
'new' => $permissions,
131+
'revoked' => true,
132+
]);
133+
119134
// Only update the database and hit up the Wings instance to invalidate JTI's if the permissions
120135
// have actually changed for the user.
121136
if ($permissions !== $current) {
122-
$this->repository->update($subuser->id, [
123-
'permissions' => $this->getDefaultPermissions($request),
124-
]);
125-
126-
try {
127-
$this->serverRepository->setServer($server)->revokeUserJTI($subuser->user_id);
128-
} catch (DaemonConnectionException $exception) {
129-
// Don't block this request if we can't connect to the Wings instance. Chances are it is
130-
// offline in this event and the token will be invalid anyways once Wings boots back.
131-
Log::warning($exception, ['user_id' => $subuser->user_id, 'server_id' => $server->id]);
132-
}
137+
$log->transaction(function ($instance) use ($request, $subuser, $server) {
138+
$this->repository->update($subuser->id, [
139+
'permissions' => $this->getDefaultPermissions($request),
140+
]);
141+
142+
try {
143+
$this->serverRepository->setServer($server)->revokeUserJTI($subuser->user_id);
144+
} catch (DaemonConnectionException $exception) {
145+
// Don't block this request if we can't connect to the Wings instance. Chances are it is
146+
// offline in this event and the token will be invalid anyways once Wings boots back.
147+
Log::warning($exception, ['user_id' => $subuser->user_id, 'server_id' => $server->id]);
148+
149+
$instance->property('revoked', false);
150+
}
151+
});
133152
}
134153

154+
$log->reset();
155+
135156
return $this->fractal->item($subuser->refresh())
136157
->transformWith($this->getTransformer(SubuserTransformer::class))
137158
->toArray();
@@ -147,14 +168,23 @@ public function delete(DeleteSubuserRequest $request, Server $server)
147168
/** @var \Pterodactyl\Models\Subuser $subuser */
148169
$subuser = $request->attributes->get('subuser');
149170

150-
$this->repository->delete($subuser->id);
171+
$log = Activity::event('server:subuser.delete')
172+
->subject($subuser->user)
173+
->property('email', $subuser->user->email)
174+
->property('revoked', true);
151175

152-
try {
153-
$this->serverRepository->setServer($server)->revokeUserJTI($subuser->user_id);
154-
} catch (DaemonConnectionException $exception) {
155-
// Don't block this request if we can't connect to the Wings instance.
156-
Log::warning($exception, ['user_id' => $subuser->user_id, 'server_id' => $server->id]);
157-
}
176+
$log->transaction(function ($instance) use ($server, $subuser) {
177+
$subuser->delete();
178+
179+
try {
180+
$this->serverRepository->setServer($server)->revokeUserJTI($subuser->user_id);
181+
} catch (DaemonConnectionException $exception) {
182+
// Don't block this request if we can't connect to the Wings instance.
183+
Log::warning($exception, ['user_id' => $subuser->user_id, 'server_id' => $server->id]);
184+
185+
$instance->property('revoked', false);
186+
}
187+
});
158188

159189
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
160190
}

app/Models/Allocation.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public function getHasAliasAttribute($value)
122122
return !is_null($this->ip_alias);
123123
}
124124

125+
public function toString(): string
126+
{
127+
return sprintf('%s:%s', $this->ip, $this->port);
128+
}
129+
125130
/**
126131
* Gets information for the server associated with this allocation.
127132
*

0 commit comments

Comments
 (0)