Skip to content

Commit cbecfff

Browse files
committed
Add activity logging for files
1 parent 0999ad7 commit cbecfff

File tree

6 files changed

+98
-108
lines changed

6 files changed

+98
-108
lines changed

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

Lines changed: 71 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
use Carbon\CarbonImmutable;
66
use Illuminate\Http\Response;
77
use Pterodactyl\Models\Server;
8-
use Pterodactyl\Models\AuditLog;
98
use Illuminate\Http\JsonResponse;
9+
use Pterodactyl\Facades\Activity;
1010
use Pterodactyl\Services\Nodes\NodeJWTService;
11-
use Illuminate\Contracts\Routing\ResponseFactory;
1211
use Pterodactyl\Repositories\Wings\DaemonFileRepository;
1312
use Pterodactyl\Transformers\Api\Client\FileObjectTransformer;
1413
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
@@ -31,11 +30,6 @@ class FileController extends ClientApiController
3130
*/
3231
private $fileRepository;
3332

34-
/**
35-
* @var \Illuminate\Contracts\Routing\ResponseFactory
36-
*/
37-
private $responseFactory;
38-
3933
/**
4034
* @var \Pterodactyl\Services\Nodes\NodeJWTService
4135
*/
@@ -45,14 +39,12 @@ class FileController extends ClientApiController
4539
* FileController constructor.
4640
*/
4741
public function __construct(
48-
ResponseFactory $responseFactory,
4942
NodeJWTService $jwtService,
5043
DaemonFileRepository $fileRepository
5144
) {
5245
parent::__construct();
5346

5447
$this->fileRepository = $fileRepository;
55-
$this->responseFactory = $responseFactory;
5648
$this->jwtService = $jwtService;
5749
}
5850

@@ -84,6 +76,8 @@ public function contents(GetFileContentsRequest $request, Server $server): Respo
8476
config('pterodactyl.files.max_edit_size')
8577
);
8678

79+
Activity::event('server:file.read')->property('file', $request->get('file'))->log();
80+
8781
return new Response($response, Response::HTTP_OK, ['Content-Type' => 'text/plain']);
8882
}
8983

@@ -97,20 +91,15 @@ public function contents(GetFileContentsRequest $request, Server $server): Respo
9791
*/
9892
public function download(GetFileContentsRequest $request, Server $server)
9993
{
100-
$token = $server->audit(
101-
AuditLog::SERVER__FILESYSTEM_DOWNLOAD,
102-
function (AuditLog $audit, Server $server) use ($request) {
103-
$audit->metadata = ['file' => $request->get('file')];
104-
105-
return $this->jwtService
106-
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
107-
->setClaims([
108-
'file_path' => rawurldecode($request->get('file')),
109-
'server_uuid' => $server->uuid,
110-
])
111-
->handle($server->node, $request->user()->id . $server->uuid);
112-
}
113-
);
94+
$token = $this->jwtService
95+
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
96+
->setClaims([
97+
'file_path' => rawurldecode($request->get('file')),
98+
'server_uuid' => $server->uuid,
99+
])
100+
->handle($server->node, $request->user()->id . $server->uuid);
101+
102+
Activity::event('server:file.download')->property('file', $request->get('file'))->log();
114103

115104
return [
116105
'object' => 'signed_url',
@@ -131,14 +120,9 @@ function (AuditLog $audit, Server $server) use ($request) {
131120
*/
132121
public function write(WriteFileContentRequest $request, Server $server): JsonResponse
133122
{
134-
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
135-
$audit->subaction = 'write_content';
136-
$audit->metadata = ['file' => $request->get('file')];
123+
$this->fileRepository->setServer($server)->putContent($request->get('file'), $request->getContent());
137124

138-
$this->fileRepository
139-
->setServer($server)
140-
->putContent($request->get('file'), $request->getContent());
141-
});
125+
Activity::event('server:file.write')->property('file', $request->get('file'))->log();
142126

143127
return new JsonResponse([], Response::HTTP_NO_CONTENT);
144128
}
@@ -150,14 +134,14 @@ public function write(WriteFileContentRequest $request, Server $server): JsonRes
150134
*/
151135
public function create(CreateFolderRequest $request, Server $server): JsonResponse
152136
{
153-
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
154-
$audit->subaction = 'create_folder';
155-
$audit->metadata = ['file' => $request->input('root', '/') . $request->input('name')];
137+
$this->fileRepository
138+
->setServer($server)
139+
->createDirectory($request->input('name'), $request->input('root', '/'));
156140

157-
$this->fileRepository
158-
->setServer($server)
159-
->createDirectory($request->input('name'), $request->input('root', '/'));
160-
});
141+
Activity::event('server:file.create-directory')
142+
->property('name', $request->input('name'))
143+
->property('directory', $request->input('root'))
144+
->log();
161145

162146
return new JsonResponse([], Response::HTTP_NO_CONTENT);
163147
}
@@ -169,13 +153,14 @@ public function create(CreateFolderRequest $request, Server $server): JsonRespon
169153
*/
170154
public function rename(RenameFileRequest $request, Server $server): JsonResponse
171155
{
172-
$server->audit(AuditLog::SERVER__FILESYSTEM_RENAME, function (AuditLog $audit, Server $server) use ($request) {
173-
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];
156+
$this->fileRepository
157+
->setServer($server)
158+
->renameFiles($request->input('root'), $request->input('files'));
174159

175-
$this->fileRepository
176-
->setServer($server)
177-
->renameFiles($request->input('root'), $request->input('files'));
178-
});
160+
Activity::event('server:file.rename')
161+
->property('directory', $request->input('root'))
162+
->property('files', $request->input('files'))
163+
->log();
179164

180165
return new JsonResponse([], Response::HTTP_NO_CONTENT);
181166
}
@@ -187,14 +172,11 @@ public function rename(RenameFileRequest $request, Server $server): JsonResponse
187172
*/
188173
public function copy(CopyFileRequest $request, Server $server): JsonResponse
189174
{
190-
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
191-
$audit->subaction = 'copy_file';
192-
$audit->metadata = ['file' => $request->input('location')];
175+
$this->fileRepository
176+
->setServer($server)
177+
->copyFile($request->input('location'));
193178

194-
$this->fileRepository
195-
->setServer($server)
196-
->copyFile($request->input('location'));
197-
});
179+
Activity::event('server:file.copy')->property('file', $request->input('location'))->log();
198180

199181
return new JsonResponse([], Response::HTTP_NO_CONTENT);
200182
}
@@ -204,22 +186,16 @@ public function copy(CopyFileRequest $request, Server $server): JsonResponse
204186
*/
205187
public function compress(CompressFilesRequest $request, Server $server): array
206188
{
207-
$file = $server->audit(
208-
AuditLog::SERVER__FILESYSTEM_COMPRESS,
209-
function (AuditLog $audit, Server $server) use ($request) {
210-
// Allow up to five minutes for this request to process before timing out.
211-
set_time_limit(300);
212-
213-
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];
214-
215-
return $this->fileRepository->setServer($server)
216-
->compressFiles(
217-
$request->input('root'),
218-
$request->input('files')
219-
);
220-
}
189+
$file = $this->fileRepository->setServer($server)->compressFiles(
190+
$request->input('root'),
191+
$request->input('files')
221192
);
222193

194+
Activity::event('server:file.compress')
195+
->property('directory', $request->input('root'))
196+
->property('files', $request->input('files'))
197+
->log();
198+
223199
return $this->fractal->item($file)
224200
->transformWith($this->getTransformer(FileObjectTransformer::class))
225201
->toArray();
@@ -230,19 +206,18 @@ function (AuditLog $audit, Server $server) use ($request) {
230206
*/
231207
public function decompress(DecompressFilesRequest $request, Server $server): JsonResponse
232208
{
233-
$file = $server->audit(
234-
AuditLog::SERVER__FILESYSTEM_DECOMPRESS,
235-
function (AuditLog $audit, Server $server) use ($request) {
236-
// Allow up to five minutes for this request to process before timing out.
237-
set_time_limit(300);
209+
set_time_limit(300);
238210

239-
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('file')];
240-
241-
$this->fileRepository->setServer($server)
242-
->decompressFile($request->input('root'), $request->input('file'));
243-
}
211+
$this->fileRepository->setServer($server)->decompressFile(
212+
$request->input('root'),
213+
$request->input('file')
244214
);
245215

216+
Activity::event('server:file.decompress')
217+
->property('directory', $request->input('root'))
218+
->property('files', $request->input('file'))
219+
->log();
220+
246221
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
247222
}
248223

@@ -253,15 +228,15 @@ function (AuditLog $audit, Server $server) use ($request) {
253228
*/
254229
public function delete(DeleteFileRequest $request, Server $server): JsonResponse
255230
{
256-
$server->audit(AuditLog::SERVER__FILESYSTEM_DELETE, function (AuditLog $audit, Server $server) use ($request) {
257-
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];
231+
$this->fileRepository->setServer($server)->deleteFiles(
232+
$request->input('root'),
233+
$request->input('files')
234+
);
258235

259-
$this->fileRepository->setServer($server)
260-
->deleteFiles(
261-
$request->input('root'),
262-
$request->input('files')
263-
);
264-
});
236+
Activity::event('server:file.delete')
237+
->property('directory', $request->input('root'))
238+
->property('files', $request->input('files'))
239+
->log();
265240

266241
return new JsonResponse([], Response::HTTP_NO_CONTENT);
267242
}
@@ -273,11 +248,10 @@ public function delete(DeleteFileRequest $request, Server $server): JsonResponse
273248
*/
274249
public function chmod(ChmodFilesRequest $request, Server $server): JsonResponse
275250
{
276-
$this->fileRepository->setServer($server)
277-
->chmodFiles(
278-
$request->input('root'),
279-
$request->input('files')
280-
);
251+
$this->fileRepository->setServer($server)->chmodFiles(
252+
$request->input('root'),
253+
$request->input('files')
254+
);
281255

282256
return new JsonResponse([], Response::HTTP_NO_CONTENT);
283257
}
@@ -289,17 +263,16 @@ public function chmod(ChmodFilesRequest $request, Server $server): JsonResponse
289263
*/
290264
public function pull(PullFileRequest $request, Server $server): JsonResponse
291265
{
292-
$server->audit(AuditLog::SERVER__FILESYSTEM_PULL, function (AuditLog $audit, Server $server) use ($request) {
293-
$audit->metadata = ['directory' => $request->input('directory'), 'url' => $request->input('url')];
294-
295-
$this->fileRepository
296-
->setServer($server)
297-
->pull(
298-
$request->input('url'),
299-
$request->input('directory'),
300-
$request->safe(['filename', 'use_header', 'foreground'])
301-
);
302-
});
266+
$this->fileRepository->setServer($server)->pull(
267+
$request->input('url'),
268+
$request->input('directory'),
269+
$request->safe(['filename', 'use_header', 'foreground'])
270+
);
271+
272+
Activity::event('server:file.pull')
273+
->property('directory', $request->input('directory'))
274+
->property('url', $request->input('url'))
275+
->log();
303276

304277
return new JsonResponse([], Response::HTTP_NO_CONTENT);
305278
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Pterodactyl\Models\User;
77
use Pterodactyl\Models\Server;
88
use Illuminate\Http\JsonResponse;
9+
use Pterodactyl\Facades\Activity;
910
use Pterodactyl\Services\Nodes\NodeJWTService;
1011
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
1112
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\UploadFileRequest;
@@ -35,6 +36,8 @@ public function __construct(
3536
*/
3637
public function __invoke(UploadFileRequest $request, Server $server)
3738
{
39+
Activity::event('server:file.upload')->log();
40+
3841
return new JsonResponse([
3942
'object' => 'signed_url',
4043
'attributes' => [

app/Models/ActivityLog.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,28 @@
1212
* @property int $id
1313
* @property string|null $batch
1414
* @property string $event
15+
* @property string $ip
1516
* @property string|null $description
1617
* @property string|null $actor_type
1718
* @property int|null $actor_id
1819
* @property string|null $subject_type
1920
* @property int|null $subject_id
2021
* @property \Illuminate\Support\Collection $properties
2122
* @property string $timestamp
22-
* @property \Illuminate\Database\Eloquent\Model|\Eloquent $actor
23-
* @property \Illuminate\Database\Eloquent\Model|\Eloquent $subject
23+
* @property IlluminateModel|\Eloquent $actor
24+
* @property IlluminateModel|\Eloquent $subject
2425
*
2526
* @method static Builder|ActivityLog forAction(string $action)
2627
* @method static Builder|ActivityLog forActor(\Illuminate\Database\Eloquent\Model $actor)
2728
* @method static Builder|ActivityLog forSubject(\Illuminate\Database\Eloquent\Model $subject)
2829
* @method static Builder|ActivityLog newModelQuery()
2930
* @method static Builder|ActivityLog newQuery()
3031
* @method static Builder|ActivityLog query()
31-
* @method static Builder|ActivityLog whereAction($value)
3232
* @method static Builder|ActivityLog whereActorId($value)
3333
* @method static Builder|ActivityLog whereActorType($value)
3434
* @method static Builder|ActivityLog whereBatch($value)
3535
* @method static Builder|ActivityLog whereDescription($value)
36+
* @method static Builder|ActivityLog whereEvent($value)
3637
* @method static Builder|ActivityLog whereId($value)
3738
* @method static Builder|ActivityLog whereIp($value)
3839
* @method static Builder|ActivityLog whereProperties($value)
@@ -57,8 +58,9 @@ class ActivityLog extends Model
5758
public static $validationRules = [
5859
'event' => ['required', 'string'],
5960
'batch' => ['nullable', 'uuid'],
61+
'ip' => ['required', 'string'],
6062
'description' => ['nullable', 'string'],
61-
'properties' => ['nullable', 'array'],
63+
'properties' => ['array'],
6264
];
6365

6466
public function actor(): MorphTo

app/Services/Activity/ActivityLogService.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ protected function getActivity(): ActivityLog
181181
}
182182

183183
$this->activity = new ActivityLog([
184+
'ip' => Request::ip(),
184185
'batch_uuid' => $this->batch->uuid(),
185186
'properties' => Collection::make([]),
186187
]);

database/migrations/2022_05_28_135717_create_activity_logs_table.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ public function up()
1717
$table->id();
1818
$table->uuid('batch')->nullable();
1919
$table->string('event')->index();
20+
$table->string('ip');
2021
$table->text('description')->nullable();
2122
$table->nullableNumericMorphs('actor');
2223
$table->nullableNumericMorphs('subject');
23-
$table->json('properties')->nullable();
24+
$table->json('properties');
2425
$table->timestamp('timestamp')->useCurrent()->onUpdate(null);
2526
});
2627
}

0 commit comments

Comments
 (0)