<?php12namespace Pterodactyl\Models;34use Carbon\Carbon;5use Illuminate\Support\Facades\Event;6use Pterodactyl\Events\ActivityLogged;7use Illuminate\Database\Eloquent\Builder;8use Illuminate\Database\Eloquent\MassPrunable;9use Illuminate\Database\Eloquent\Relations\HasOne;10use Illuminate\Database\Eloquent\Relations\HasMany;11use Illuminate\Database\Eloquent\Relations\MorphTo;12use Illuminate\Database\Eloquent\Model as IlluminateModel;1314/**15* \Pterodactyl\Models\ActivityLog.16*17* @property int $id18* @property string|null $batch19* @property string $event20* @property string $ip21* @property string|null $description22* @property string|null $actor_type23* @property int|null $actor_id24* @property int|null $api_key_id25* @property \Illuminate\Support\Collection|null $properties26* @property Carbon $timestamp27* @property IlluminateModel|\Eloquent $actor28* @property \Illuminate\Database\Eloquent\Collection<int, \Pterodactyl\Models\ActivityLogSubject> $subjects29* @property int|null $subjects_count30* @property ApiKey|null $apiKey31*32* @method static Builder|ActivityLog forActor(\Illuminate\Database\Eloquent\Model $actor)33* @method static Builder|ActivityLog forEvent(string $action)34* @method static Builder|ActivityLog newModelQuery()35* @method static Builder|ActivityLog newQuery()36* @method static Builder|ActivityLog query()37* @method static Builder|ActivityLog whereActorId($value)38* @method static Builder|ActivityLog whereActorType($value)39* @method static Builder|ActivityLog whereApiKeyId($value)40* @method static Builder|ActivityLog whereBatch($value)41* @method static Builder|ActivityLog whereDescription($value)42* @method static Builder|ActivityLog whereEvent($value)43* @method static Builder|ActivityLog whereId($value)44* @method static Builder|ActivityLog whereIp($value)45* @method static Builder|ActivityLog whereProperties($value)46* @method static Builder|ActivityLog whereTimestamp($value)47*48* @mixin \Eloquent49*/50class ActivityLog extends Model51{52use MassPrunable;5354public const RESOURCE_NAME = 'activity_log';5556/**57* Tracks all the events we no longer wish to display to users. These are either legacy58* events or just events where we never ended up using the associated data.59*/60public const DISABLED_EVENTS = ['server:file.upload'];6162public $timestamps = false;6364protected $guarded = [65'id',66'timestamp',67];6869protected $casts = [70'properties' => 'collection',71'timestamp' => 'datetime',72];7374protected $with = ['subjects'];7576public static array $validationRules = [77'event' => ['required', 'string'],78'batch' => ['nullable', 'uuid'],79'ip' => ['required', 'string'],80'description' => ['nullable', 'string'],81'properties' => ['array'],82];8384/**85* @return \Illuminate\Database\Eloquent\Relations\MorphTo<\Illuminate\Database\Eloquent\Model, $this>86*/87public function actor(): MorphTo88{89$morph = $this->morphTo();90if (method_exists($morph, 'withTrashed')) { // @phpstan-ignore function.alreadyNarrowedType91return $morph->withTrashed();92}9394return $morph;95}9697/**98* @return \Illuminate\Database\Eloquent\Relations\HasMany<\Pterodactyl\Models\ActivityLogSubject, $this>99*/100public function subjects(): HasMany101{102return $this->hasMany(ActivityLogSubject::class);103}104105/**106* @return \Illuminate\Database\Eloquent\Relations\HasOne<\Pterodactyl\Models\ApiKey, $this>107*/108public function apiKey(): HasOne109{110return $this->hasOne(ApiKey::class, 'id', 'api_key_id');111}112113public function scopeForEvent(Builder $builder, string $action): Builder114{115return $builder->where('event', $action);116}117118/**119* Scopes a query to only return results where the actor is a given model.120*/121public function scopeForActor(Builder $builder, IlluminateModel $actor): Builder122{123return $builder->whereMorphedTo('actor', $actor);124}125126/**127* Returns models to be pruned.128*129* @see https://laravel.com/docs/9.x/eloquent#pruning-models130*/131public function prunable()132{133if (is_null(config('activity.prune_days'))) {134throw new \LogicException('Cannot prune activity logs: no "prune_days" configuration value is set.');135}136137return static::where('timestamp', '<=', Carbon::now()->subDays(config('activity.prune_days')));138}139140/**141* Boots the model event listeners. This will trigger an activity log event every142* time a new model is inserted which can then be captured and worked with as needed.143*/144protected static function boot()145{146parent::boot();147148static::created(function (self $model) {149Event::dispatch(new ActivityLogged($model));150});151}152}153154155