mirror of
https://github.com/freescout-helpdesk/freescout.git
synced 2024-11-23 19:02:46 +01:00
Fix Guard bypass in Eloquent models in laravel/framework
This commit is contained in:
parent
1e871813f8
commit
21d86327b9
@ -125,8 +125,10 @@
|
||||
"Illuminate\\Support\\": "overrides/laravel/framework/src/Illuminate/Support/",
|
||||
"Illuminate\\Http\\": "overrides/laravel/framework/src/Illuminate/Http/",
|
||||
"Illuminate\\Database\\Eloquent\\": "overrides/laravel/framework/src/Illuminate/Database/Eloquent/",
|
||||
"Illuminate\\Database\\Eloquent\\Concerns\\": "overrides/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/",
|
||||
"Illuminate\\Pagination\\": "overrides/laravel/framework/src/Illuminate/Pagination/",
|
||||
"Illuminate\\Session\\": "overrides/laravel/framework/src/Illuminate/Session/",
|
||||
"Illuminate\\Queue\\": "overrides/laravel/framework/src/Illuminate/Queue/",
|
||||
"Carbon\\": "overrides/nesbot/carbon/src/Carbon/",
|
||||
"Illuminate\\Cache\\": "overrides/laravel/framework/src/Illuminate/Cache/",
|
||||
"Illuminate\\Config\\": "overrides/laravel/framework/src/Illuminate/Config/",
|
||||
@ -220,11 +222,13 @@
|
||||
"vendor/symfony/http-foundation/FileBag.php",
|
||||
"vendor/symfony/http-foundation/Request.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Pagination/AbstractPaginator.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Pagination/Paginator.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Pagination/LengthAwarePaginator.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Queue/Listener.php",
|
||||
"vendor/nesbot/carbon/src/Carbon/Carbon.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Cache/Repository.php",
|
||||
"vendor/laravel/framework/src/Illuminate/Config/Repository.php",
|
||||
|
@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait GuardsAttributes
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = ['*'];
|
||||
|
||||
/**
|
||||
* Indicates if all mass assignment is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $unguarded = false;
|
||||
|
||||
/**
|
||||
* The actual columns that exist on the database and can be guarded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $guardableColumns = [];
|
||||
|
||||
/**
|
||||
* Get the fillable attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFillable()
|
||||
{
|
||||
return $this->fillable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fillable attributes for the model.
|
||||
*
|
||||
* @param array $fillable
|
||||
* @return $this
|
||||
*/
|
||||
public function fillable(array $fillable)
|
||||
{
|
||||
$this->fillable = $fillable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guarded attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGuarded()
|
||||
{
|
||||
return $this->guarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the guarded attributes for the model.
|
||||
*
|
||||
* @param array $guarded
|
||||
* @return $this
|
||||
*/
|
||||
public function guard(array $guarded)
|
||||
{
|
||||
$this->guarded = $guarded;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all mass assignable restrictions.
|
||||
*
|
||||
* @param bool $state
|
||||
* @return void
|
||||
*/
|
||||
public static function unguard($state = true)
|
||||
{
|
||||
static::$unguarded = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the mass assignment restrictions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reguard()
|
||||
{
|
||||
static::$unguarded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if current state is "unguarded".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUnguarded()
|
||||
{
|
||||
return static::$unguarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given callable while being unguarded.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unguarded(callable $callback)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
static::unguard();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
static::reguard();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given attribute may be mass assigned.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isFillable($key)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the key is in the "fillable" array, we can of course assume that it's
|
||||
// a fillable attribute. Otherwise, we will check the guarded array when
|
||||
// we need to determine if the attribute is black-listed on the model.
|
||||
if (in_array($key, $this->getFillable())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the attribute is explicitly listed in the "guarded" array then we can
|
||||
// return false immediately. This means this attribute is definitely not
|
||||
// fillable and there is no point in going any further in this method.
|
||||
if ($this->isGuarded($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return empty($this->getFillable()) &&
|
||||
strpos($key, '.') === false &&
|
||||
! Str::startsWith($key, '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key is guarded.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isGuarded($key)
|
||||
{
|
||||
//return in_array($key, $this->getGuarded()) || $this->getGuarded() == ['*'];
|
||||
|
||||
if (empty($this->getGuarded())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getGuarded() == ['*'] ||
|
||||
! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())) ||
|
||||
! $this->isGuardableColumn($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given column is a valid, guardable column.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function isGuardableColumn($key)
|
||||
{
|
||||
if (! isset(static::$guardableColumns[get_class($this)])) {
|
||||
static::$guardableColumns[get_class($this)] = $this->getConnection()
|
||||
->getSchemaBuilder()
|
||||
->getColumnListing($this->getTable());
|
||||
}
|
||||
|
||||
return in_array($key, static::$guardableColumns[get_class($this)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is totally guarded.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function totallyGuarded()
|
||||
{
|
||||
return count($this->getFillable()) == 0 && $this->getGuarded() == ['*'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fillable attributes of a given array.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function fillableFromArray(array $attributes)
|
||||
{
|
||||
if (count($this->getFillable()) > 0 && ! static::$unguarded) {
|
||||
return array_intersect_key($attributes, array_flip($this->getFillable()));
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
@ -272,7 +272,8 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab
|
||||
*/
|
||||
protected function removeTableFromKey($key)
|
||||
{
|
||||
return Str::contains($key, '.') ? last(explode('.', $key)) : $key;
|
||||
//return Str::contains($key, '.') ? last(explode('.', $key)) : $key;
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
|
248
overrides/laravel/framework/src/Illuminate/Queue/Listener.php
Normal file
248
overrides/laravel/framework/src/Illuminate/Queue/Listener.php
Normal file
@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Queue;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\ProcessUtils;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\PhpExecutableFinder;
|
||||
|
||||
class Listener
|
||||
{
|
||||
/**
|
||||
* The command working path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $commandPath;
|
||||
|
||||
/**
|
||||
* The environment the workers should run under.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $environment;
|
||||
|
||||
/**
|
||||
* The amount of seconds to wait before polling the queue.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $sleep = 3;
|
||||
|
||||
/**
|
||||
* The amount of times to try a job before logging it failed.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $maxTries = 0;
|
||||
|
||||
/**
|
||||
* The queue worker command line.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $workerCommand;
|
||||
|
||||
/**
|
||||
* The output handler callback.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
protected $outputHandler;
|
||||
|
||||
/**
|
||||
* Create a new queue listener.
|
||||
*
|
||||
* @param string $commandPath
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($commandPath)
|
||||
{
|
||||
$this->commandPath = $commandPath;
|
||||
$this->workerCommand = $this->buildCommandTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the environment specific worker command.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildCommandTemplate()
|
||||
{
|
||||
$command = 'queue:work %s --once --queue=%s --delay=%s --memory=%s --sleep=%s --tries=%s';
|
||||
|
||||
return "{$this->phpBinary()} {$this->artisanBinary()} {$command}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PHP binary.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function phpBinary()
|
||||
{
|
||||
return ProcessUtils::escapeArgument(
|
||||
(new PhpExecutableFinder)->find(false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Artisan binary.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function artisanBinary()
|
||||
{
|
||||
return defined('ARTISAN_BINARY')
|
||||
? ProcessUtils::escapeArgument(ARTISAN_BINARY)
|
||||
: 'artisan';
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the given queue connection.
|
||||
*
|
||||
* @param string $connection
|
||||
* @param string $queue
|
||||
* @param \Illuminate\Queue\ListenerOptions $options
|
||||
* @return void
|
||||
*/
|
||||
public function listen($connection, $queue, ListenerOptions $options)
|
||||
{
|
||||
$process = $this->makeProcess($connection, $queue, $options);
|
||||
|
||||
while (true) {
|
||||
$this->runProcess($process, $options->memory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Symfony process for the worker.
|
||||
*
|
||||
* @param string $connection
|
||||
* @param string $queue
|
||||
* @param \Illuminate\Queue\ListenerOptions $options
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
public function makeProcess($connection, $queue, ListenerOptions $options)
|
||||
{
|
||||
$command = $this->workerCommand;
|
||||
|
||||
// If the environment is set, we will append it to the command string so the
|
||||
// workers will run under the specified environment. Otherwise, they will
|
||||
// just run under the production environment which is not always right.
|
||||
if (isset($options->environment)) {
|
||||
$command = $this->addEnvironment($command, $options);
|
||||
}
|
||||
|
||||
// Next, we will just format out the worker commands with all of the various
|
||||
// options available for the command. This will produce the final command
|
||||
// line that we will pass into a Symfony process object for processing.
|
||||
$command = $this->formatCommand(
|
||||
$command, $connection, $queue, $options
|
||||
);
|
||||
|
||||
return new Process(
|
||||
$command, $this->commandPath, null, null, $options->timeout
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the environment option to the given command.
|
||||
*
|
||||
* @param string $command
|
||||
* @param \Illuminate\Queue\ListenerOptions $options
|
||||
* @return string
|
||||
*/
|
||||
protected function addEnvironment($command, ListenerOptions $options)
|
||||
{
|
||||
return $command.' --env='.ProcessUtils::escapeArgument($options->environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given command with the listener options.
|
||||
*
|
||||
* @param string $command
|
||||
* @param string $connection
|
||||
* @param string $queue
|
||||
* @param \Illuminate\Queue\ListenerOptions $options
|
||||
* @return string
|
||||
*/
|
||||
protected function formatCommand($command, $connection, $queue, ListenerOptions $options)
|
||||
{
|
||||
return sprintf(
|
||||
$command,
|
||||
ProcessUtils::escapeArgument($connection),
|
||||
ProcessUtils::escapeArgument($queue),
|
||||
$options->delay, $options->memory,
|
||||
$options->sleep, $options->maxTries
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given process.
|
||||
*
|
||||
* @param \Symfony\Component\Process\Process $process
|
||||
* @param int $memory
|
||||
* @return void
|
||||
*/
|
||||
public function runProcess(Process $process, $memory)
|
||||
{
|
||||
$process->run(function ($type, $line) {
|
||||
$this->handleWorkerOutput($type, $line);
|
||||
});
|
||||
|
||||
// Once we have run the job we'll go check if the memory limit has been exceeded
|
||||
// for the script. If it has, we will kill this script so the process manager
|
||||
// will restart this with a clean slate of memory automatically on exiting.
|
||||
if ($this->memoryExceeded($memory)) {
|
||||
$this->stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle output from the worker process.
|
||||
*
|
||||
* @param int $type
|
||||
* @param string $line
|
||||
* @return void
|
||||
*/
|
||||
protected function handleWorkerOutput($type, $line)
|
||||
{
|
||||
if (isset($this->outputHandler)) {
|
||||
call_user_func($this->outputHandler, $type, $line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the memory limit has been exceeded.
|
||||
*
|
||||
* @param int $memoryLimit
|
||||
* @return bool
|
||||
*/
|
||||
public function memoryExceeded($memoryLimit)
|
||||
{
|
||||
return (memory_get_usage() / 1024 / 1024) >= $memoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop listening and bail out of the script.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output handler callback.
|
||||
*
|
||||
* @param \Closure $outputHandler
|
||||
* @return void
|
||||
*/
|
||||
public function setOutputHandler(Closure $outputHandler)
|
||||
{
|
||||
$this->outputHandler = $outputHandler;
|
||||
}
|
||||
}
|
@ -275,7 +275,7 @@ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate
|
||||
|
||||
call_user_func_array([$this, 'dump'], $args);
|
||||
|
||||
die(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user