forked from pterodactyl/panel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new activity logging code to replace audit log
- Loading branch information
1 parent
c14c7b4
commit 5bb66a0
Showing
11 changed files
with
534 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Facades; | ||
|
||
use Illuminate\Support\Facades\Facade; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Pterodactyl\Services\Activity\ActivityLogService; | ||
|
||
/** | ||
* @method static ActivityLogService anonymous() | ||
* @method static ActivityLogService event(string $action) | ||
* @method static ActivityLogService withDescription(?string $description) | ||
* @method static ActivityLogService withSubject(Model $subject) | ||
* @method static ActivityLogService withActor(Model $actor) | ||
* @method static ActivityLogService withProperties(\Illuminate\Support\Collection|array $properties) | ||
* @method static ActivityLogService withProperty(string $key, mixed $value) | ||
* @method static mixed transaction(\Closure $callback) | ||
*/ | ||
class Activity extends Facade | ||
{ | ||
protected static function getFacadeAccessor() | ||
{ | ||
return ActivityLogService::class; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Facades; | ||
|
||
use Illuminate\Support\Facades\Facade; | ||
use Pterodactyl\Services\Activity\AcitvityLogBatchService; | ||
|
||
/** | ||
* @method static ?string uuid() | ||
* @method static void start() | ||
* @method static void end() | ||
* @method static mixed transaction(\Closure $callback) | ||
*/ | ||
class LogBatch extends Facade | ||
{ | ||
protected static function getFacadeAccessor() | ||
{ | ||
return AcitvityLogBatchService::class; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Facades; | ||
|
||
use Illuminate\Support\Facades\Facade; | ||
use Pterodactyl\Services\Activity\ActivityLogTargetableService; | ||
|
||
/** | ||
* @method static void setActor(\Illuminate\Database\Eloquent\Model $actor) | ||
* @method static void setSubject(\Illuminate\Database\Eloquent\Model $subject) | ||
* @method static \Illuminate\Database\Eloquent\Model|null actor() | ||
* @method static \Illuminate\Database\Eloquent\Model|null subject() | ||
* @method static void reset() | ||
*/ | ||
class LogTarget extends Facade | ||
{ | ||
protected static function getFacadeAccessor() | ||
{ | ||
return ActivityLogTargetableService::class; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Http\Middleware; | ||
|
||
use Closure; | ||
use Illuminate\Http\Request; | ||
use Pterodactyl\Models\Server; | ||
use Pterodactyl\Facades\LogTarget; | ||
|
||
class ServerActivityLogs | ||
{ | ||
/** | ||
* Attempts to automatically scope all of the activity log events registered | ||
* within the request instance to the given user and server. This only sets | ||
* the actor and subject if there is a server present on the request. | ||
* | ||
* If no server is found this is a no-op as the activity log service can always | ||
* set the user based on the authmanager response. | ||
*/ | ||
public function handle(Request $request, Closure $next) | ||
{ | ||
$server = $request->route()->parameter('server'); | ||
if ($server instanceof Server) { | ||
LogTarget::setActor($request->user()); | ||
LogTarget::setSubject($server); | ||
} | ||
|
||
return $next($request); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Models; | ||
|
||
use Illuminate\Database\Eloquent\Builder; | ||
use Illuminate\Database\Eloquent\Relations\MorphTo; | ||
use Illuminate\Database\Eloquent\Model as IlluminateModel; | ||
|
||
/** | ||
* \Pterodactyl\Models\ActivityLog. | ||
* | ||
* @property int $id | ||
* @property string|null $batch | ||
* @property string $event | ||
* @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 | ||
* | ||
* @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 whereId($value) | ||
* @method static Builder|ActivityLog whereIp($value) | ||
* @method static Builder|ActivityLog whereProperties($value) | ||
* @method static Builder|ActivityLog whereSubjectId($value) | ||
* @method static Builder|ActivityLog whereSubjectType($value) | ||
* @method static Builder|ActivityLog whereTimestamp($value) | ||
* @mixin \Eloquent | ||
*/ | ||
class ActivityLog extends Model | ||
{ | ||
public $timestamps = false; | ||
|
||
protected $guarded = [ | ||
'id', | ||
'timestamp', | ||
]; | ||
|
||
protected $casts = [ | ||
'properties' => 'collection', | ||
]; | ||
|
||
public static $validationRules = [ | ||
'event' => ['required', 'string'], | ||
'batch' => ['nullable', 'uuid'], | ||
'description' => ['nullable', 'string'], | ||
'properties' => ['nullable', 'array'], | ||
]; | ||
|
||
public function actor(): MorphTo | ||
{ | ||
return $this->morphTo(); | ||
} | ||
|
||
public function subject(): MorphTo | ||
{ | ||
return $this->morphTo(); | ||
} | ||
|
||
public function scopeForAction(Builder $builder, string $action): Builder | ||
{ | ||
return $builder->where('action', $action); | ||
} | ||
|
||
/** | ||
* Scopes a query to only return results where the actor is a given model. | ||
*/ | ||
public function scopeForActor(Builder $builder, IlluminateModel $actor): Builder | ||
{ | ||
return $builder->whereMorphedTo('actor', $actor); | ||
} | ||
|
||
/** | ||
* Scopes a query to only return results where the subject is the given model. | ||
*/ | ||
public function scopeForSubject(Builder $builder, IlluminateModel $subject): Builder | ||
{ | ||
return $builder->whereMorphedTo('subject', $subject); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Providers; | ||
|
||
use Illuminate\Support\ServiceProvider; | ||
use Pterodactyl\Services\Activity\AcitvityLogBatchService; | ||
use Pterodactyl\Services\Activity\ActivityLogTargetableService; | ||
|
||
class ActivityLogServiceProvider extends ServiceProvider | ||
{ | ||
/** | ||
* Registers the necessary activity logger singletons scoped to the individual | ||
* request instances. | ||
*/ | ||
public function register() | ||
{ | ||
$this->app->scoped(AcitvityLogBatchService::class); | ||
$this->app->scoped(ActivityLogTargetableService::class); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
namespace Pterodactyl\Services\Activity; | ||
|
||
use Ramsey\Uuid\Uuid; | ||
|
||
class AcitvityLogBatchService | ||
{ | ||
protected int $transaction = 0; | ||
protected ?string $uuid = null; | ||
|
||
/** | ||
* Returns the UUID of the batch, or null if there is not a batch currently | ||
* being executed. | ||
*/ | ||
public function uuid(): ?string | ||
{ | ||
return $this->uuid; | ||
} | ||
|
||
/** | ||
* Starts a new batch transaction. If there is already a transaction present | ||
* this will be nested. | ||
*/ | ||
public function start(): void | ||
{ | ||
if ($this->transaction === 0) { | ||
$this->uuid = Uuid::uuid4()->toString(); | ||
} | ||
|
||
++$this->transaction; | ||
} | ||
|
||
/** | ||
* Ends a batch transaction, if this is the last transaction in the stack | ||
* the UUID will be cleared out. | ||
*/ | ||
public function end(): void | ||
{ | ||
$this->transaction = max(0, $this->transaction - 1); | ||
|
||
if ($this->transaction === 0) { | ||
$this->uuid = null; | ||
} | ||
} | ||
|
||
/** | ||
* Executes the logic provided within the callback in the scope of an activity | ||
* log batch transaction. | ||
* | ||
* @param \Closure $callback | ||
* @return mixed | ||
*/ | ||
public function transaction(\Closure $callback) | ||
{ | ||
$this->start(); | ||
$result = $callback($this->uuid()); | ||
$this->end(); | ||
|
||
return $result; | ||
} | ||
} |
Oops, something went wrong.