Skip to content

Commit

Permalink
Add activity logging for files
Browse files Browse the repository at this point in the history
  • Loading branch information
DaneEveritt committed May 29, 2022
1 parent 0999ad7 commit cbecfff
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 108 deletions.
169 changes: 71 additions & 98 deletions app/Http/Controllers/Api/Client/Servers/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
use Carbon\CarbonImmutable;
use Illuminate\Http\Response;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\AuditLog;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Facades\Activity;
use Pterodactyl\Services\Nodes\NodeJWTService;
use Illuminate\Contracts\Routing\ResponseFactory;
use Pterodactyl\Repositories\Wings\DaemonFileRepository;
use Pterodactyl\Transformers\Api\Client\FileObjectTransformer;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
Expand All @@ -31,11 +30,6 @@ class FileController extends ClientApiController
*/
private $fileRepository;

/**
* @var \Illuminate\Contracts\Routing\ResponseFactory
*/
private $responseFactory;

/**
* @var \Pterodactyl\Services\Nodes\NodeJWTService
*/
Expand All @@ -45,14 +39,12 @@ class FileController extends ClientApiController
* FileController constructor.
*/
public function __construct(
ResponseFactory $responseFactory,
NodeJWTService $jwtService,
DaemonFileRepository $fileRepository
) {
parent::__construct();

$this->fileRepository = $fileRepository;
$this->responseFactory = $responseFactory;
$this->jwtService = $jwtService;
}

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

Activity::event('server:file.read')->property('file', $request->get('file'))->log();

return new Response($response, Response::HTTP_OK, ['Content-Type' => 'text/plain']);
}

Expand All @@ -97,20 +91,15 @@ public function contents(GetFileContentsRequest $request, Server $server): Respo
*/
public function download(GetFileContentsRequest $request, Server $server)
{
$token = $server->audit(
AuditLog::SERVER__FILESYSTEM_DOWNLOAD,
function (AuditLog $audit, Server $server) use ($request) {
$audit->metadata = ['file' => $request->get('file')];

return $this->jwtService
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
->setClaims([
'file_path' => rawurldecode($request->get('file')),
'server_uuid' => $server->uuid,
])
->handle($server->node, $request->user()->id . $server->uuid);
}
);
$token = $this->jwtService
->setExpiresAt(CarbonImmutable::now()->addMinutes(15))
->setClaims([
'file_path' => rawurldecode($request->get('file')),
'server_uuid' => $server->uuid,
])
->handle($server->node, $request->user()->id . $server->uuid);

Activity::event('server:file.download')->property('file', $request->get('file'))->log();

return [
'object' => 'signed_url',
Expand All @@ -131,14 +120,9 @@ function (AuditLog $audit, Server $server) use ($request) {
*/
public function write(WriteFileContentRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
$audit->subaction = 'write_content';
$audit->metadata = ['file' => $request->get('file')];
$this->fileRepository->setServer($server)->putContent($request->get('file'), $request->getContent());

$this->fileRepository
->setServer($server)
->putContent($request->get('file'), $request->getContent());
});
Activity::event('server:file.write')->property('file', $request->get('file'))->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -150,14 +134,14 @@ public function write(WriteFileContentRequest $request, Server $server): JsonRes
*/
public function create(CreateFolderRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
$audit->subaction = 'create_folder';
$audit->metadata = ['file' => $request->input('root', '/') . $request->input('name')];
$this->fileRepository
->setServer($server)
->createDirectory($request->input('name'), $request->input('root', '/'));

$this->fileRepository
->setServer($server)
->createDirectory($request->input('name'), $request->input('root', '/'));
});
Activity::event('server:file.create-directory')
->property('name', $request->input('name'))
->property('directory', $request->input('root'))
->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -169,13 +153,14 @@ public function create(CreateFolderRequest $request, Server $server): JsonRespon
*/
public function rename(RenameFileRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_RENAME, function (AuditLog $audit, Server $server) use ($request) {
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];
$this->fileRepository
->setServer($server)
->renameFiles($request->input('root'), $request->input('files'));

$this->fileRepository
->setServer($server)
->renameFiles($request->input('root'), $request->input('files'));
});
Activity::event('server:file.rename')
->property('directory', $request->input('root'))
->property('files', $request->input('files'))
->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -187,14 +172,11 @@ public function rename(RenameFileRequest $request, Server $server): JsonResponse
*/
public function copy(CopyFileRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_WRITE, function (AuditLog $audit, Server $server) use ($request) {
$audit->subaction = 'copy_file';
$audit->metadata = ['file' => $request->input('location')];
$this->fileRepository
->setServer($server)
->copyFile($request->input('location'));

$this->fileRepository
->setServer($server)
->copyFile($request->input('location'));
});
Activity::event('server:file.copy')->property('file', $request->input('location'))->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -204,22 +186,16 @@ public function copy(CopyFileRequest $request, Server $server): JsonResponse
*/
public function compress(CompressFilesRequest $request, Server $server): array
{
$file = $server->audit(
AuditLog::SERVER__FILESYSTEM_COMPRESS,
function (AuditLog $audit, Server $server) use ($request) {
// Allow up to five minutes for this request to process before timing out.
set_time_limit(300);

$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];

return $this->fileRepository->setServer($server)
->compressFiles(
$request->input('root'),
$request->input('files')
);
}
$file = $this->fileRepository->setServer($server)->compressFiles(
$request->input('root'),
$request->input('files')
);

Activity::event('server:file.compress')
->property('directory', $request->input('root'))
->property('files', $request->input('files'))
->log();

return $this->fractal->item($file)
->transformWith($this->getTransformer(FileObjectTransformer::class))
->toArray();
Expand All @@ -230,19 +206,18 @@ function (AuditLog $audit, Server $server) use ($request) {
*/
public function decompress(DecompressFilesRequest $request, Server $server): JsonResponse
{
$file = $server->audit(
AuditLog::SERVER__FILESYSTEM_DECOMPRESS,
function (AuditLog $audit, Server $server) use ($request) {
// Allow up to five minutes for this request to process before timing out.
set_time_limit(300);
set_time_limit(300);

$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('file')];

$this->fileRepository->setServer($server)
->decompressFile($request->input('root'), $request->input('file'));
}
$this->fileRepository->setServer($server)->decompressFile(
$request->input('root'),
$request->input('file')
);

Activity::event('server:file.decompress')
->property('directory', $request->input('root'))
->property('files', $request->input('file'))
->log();

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

Expand All @@ -253,15 +228,15 @@ function (AuditLog $audit, Server $server) use ($request) {
*/
public function delete(DeleteFileRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_DELETE, function (AuditLog $audit, Server $server) use ($request) {
$audit->metadata = ['root' => $request->input('root'), 'files' => $request->input('files')];
$this->fileRepository->setServer($server)->deleteFiles(
$request->input('root'),
$request->input('files')
);

$this->fileRepository->setServer($server)
->deleteFiles(
$request->input('root'),
$request->input('files')
);
});
Activity::event('server:file.delete')
->property('directory', $request->input('root'))
->property('files', $request->input('files'))
->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -273,11 +248,10 @@ public function delete(DeleteFileRequest $request, Server $server): JsonResponse
*/
public function chmod(ChmodFilesRequest $request, Server $server): JsonResponse
{
$this->fileRepository->setServer($server)
->chmodFiles(
$request->input('root'),
$request->input('files')
);
$this->fileRepository->setServer($server)->chmodFiles(
$request->input('root'),
$request->input('files')
);

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand All @@ -289,17 +263,16 @@ public function chmod(ChmodFilesRequest $request, Server $server): JsonResponse
*/
public function pull(PullFileRequest $request, Server $server): JsonResponse
{
$server->audit(AuditLog::SERVER__FILESYSTEM_PULL, function (AuditLog $audit, Server $server) use ($request) {
$audit->metadata = ['directory' => $request->input('directory'), 'url' => $request->input('url')];

$this->fileRepository
->setServer($server)
->pull(
$request->input('url'),
$request->input('directory'),
$request->safe(['filename', 'use_header', 'foreground'])
);
});
$this->fileRepository->setServer($server)->pull(
$request->input('url'),
$request->input('directory'),
$request->safe(['filename', 'use_header', 'foreground'])
);

Activity::event('server:file.pull')
->property('directory', $request->input('directory'))
->property('url', $request->input('url'))
->log();

return new JsonResponse([], Response::HTTP_NO_CONTENT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Facades\Activity;
use Pterodactyl\Services\Nodes\NodeJWTService;
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\UploadFileRequest;
Expand Down Expand Up @@ -35,6 +36,8 @@ public function __construct(
*/
public function __invoke(UploadFileRequest $request, Server $server)
{
Activity::event('server:file.upload')->log();

return new JsonResponse([
'object' => 'signed_url',
'attributes' => [
Expand Down
10 changes: 6 additions & 4 deletions app/Models/ActivityLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,28 @@
* @property int $id
* @property string|null $batch
* @property string $event
* @property string $ip
* @property string|null $description
* @property string|null $actor_type
* @property int|null $actor_id
* @property string|null $subject_type
* @property int|null $subject_id
* @property \Illuminate\Support\Collection $properties
* @property string $timestamp
* @property \Illuminate\Database\Eloquent\Model|\Eloquent $actor
* @property \Illuminate\Database\Eloquent\Model|\Eloquent $subject
* @property IlluminateModel|\Eloquent $actor
* @property IlluminateModel|\Eloquent $subject
*
* @method static Builder|ActivityLog forAction(string $action)
* @method static Builder|ActivityLog forActor(\Illuminate\Database\Eloquent\Model $actor)
* @method static Builder|ActivityLog forSubject(\Illuminate\Database\Eloquent\Model $subject)
* @method static Builder|ActivityLog newModelQuery()
* @method static Builder|ActivityLog newQuery()
* @method static Builder|ActivityLog query()
* @method static Builder|ActivityLog whereAction($value)
* @method static Builder|ActivityLog whereActorId($value)
* @method static Builder|ActivityLog whereActorType($value)
* @method static Builder|ActivityLog whereBatch($value)
* @method static Builder|ActivityLog whereDescription($value)
* @method static Builder|ActivityLog whereEvent($value)
* @method static Builder|ActivityLog whereId($value)
* @method static Builder|ActivityLog whereIp($value)
* @method static Builder|ActivityLog whereProperties($value)
Expand All @@ -57,8 +58,9 @@ class ActivityLog extends Model
public static $validationRules = [
'event' => ['required', 'string'],
'batch' => ['nullable', 'uuid'],
'ip' => ['required', 'string'],
'description' => ['nullable', 'string'],
'properties' => ['nullable', 'array'],
'properties' => ['array'],
];

public function actor(): MorphTo
Expand Down
1 change: 1 addition & 0 deletions app/Services/Activity/ActivityLogService.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ protected function getActivity(): ActivityLog
}

$this->activity = new ActivityLog([
'ip' => Request::ip(),
'batch_uuid' => $this->batch->uuid(),
'properties' => Collection::make([]),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ public function up()
$table->id();
$table->uuid('batch')->nullable();
$table->string('event')->index();
$table->string('ip');
$table->text('description')->nullable();
$table->nullableNumericMorphs('actor');
$table->nullableNumericMorphs('subject');
$table->json('properties')->nullable();
$table->json('properties');
$table->timestamp('timestamp')->useCurrent()->onUpdate(null);
});
}
Expand Down
Loading

0 comments on commit cbecfff

Please sign in to comment.