From 31d004b08ace0d0a8cba3934f70eecb542bb8e29 Mon Sep 17 00:00:00 2001 From: Karl Pierce Date: Wed, 19 Aug 2020 15:08:22 -0700 Subject: [PATCH 1/5] Use parent Builder's constructor. Ours was incomplete in that it didn't initialize $this->grammar --- src/Jenssegers/Mongodb/Schema/Builder.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Jenssegers/Mongodb/Schema/Builder.php b/src/Jenssegers/Mongodb/Schema/Builder.php index c01d12426..dcad10aa9 100644 --- a/src/Jenssegers/Mongodb/Schema/Builder.php +++ b/src/Jenssegers/Mongodb/Schema/Builder.php @@ -7,14 +7,6 @@ class Builder extends \Illuminate\Database\Schema\Builder { - /** - * @inheritdoc - */ - public function __construct(Connection $connection) - { - $this->connection = $connection; - } - /** * @inheritdoc */ From 02d427bfccaa085472e78e8b4870eda6f5724308 Mon Sep 17 00:00:00 2001 From: Karl Pierce Date: Wed, 19 Aug 2020 15:09:28 -0700 Subject: [PATCH 2/5] Override Model::isGuardableColumn() to return true, since we don't really have columns --- src/Jenssegers/Mongodb/Eloquent/Model.php | 11 +++++++++++ tests/ModelTest.php | 7 +++++++ tests/models/Guarded.php | 11 +++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/models/Guarded.php diff --git a/src/Jenssegers/Mongodb/Eloquent/Model.php b/src/Jenssegers/Mongodb/Eloquent/Model.php index 9e1cf9bd7..8aaef55bb 100644 --- a/src/Jenssegers/Mongodb/Eloquent/Model.php +++ b/src/Jenssegers/Mongodb/Eloquent/Model.php @@ -473,6 +473,17 @@ protected function getRelationsWithoutParent() return $relations; } + /** + * Checks if column exists on a table. As this is a document model, just return true. This also + * prevents calls to non-existent function Grammar::compileColumnListing() + * @param string $key + * @return bool + */ + protected function isGuardableColumn($key) + { + return true; + } + /** * @inheritdoc */ diff --git a/tests/ModelTest.php b/tests/ModelTest.php index 6c1edc5a1..3ce3b1efc 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -722,4 +722,11 @@ public function testTruncateModel() $this->assertEquals(0, User::count()); } + + public function testGuardedModel() + { + Guarded::create(['var' => 'val']); + + $this->assertEquals(1, Guarded::count()); + } } diff --git a/tests/models/Guarded.php b/tests/models/Guarded.php new file mode 100644 index 000000000..4d2a3a617 --- /dev/null +++ b/tests/models/Guarded.php @@ -0,0 +1,11 @@ + Date: Wed, 19 Aug 2020 15:27:47 -0700 Subject: [PATCH 3/5] Truncate Guarded collection in tests --- tests/ModelTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ModelTest.php b/tests/ModelTest.php index 3ce3b1efc..c4a2cf661 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -19,6 +19,7 @@ public function tearDown(): void Soft::truncate(); Book::truncate(); Item::truncate(); + Guarded::truncate(); } public function testNewModel(): void From dff46269267c902a9a8a3515c76319f7ef6f3b9c Mon Sep 17 00:00:00 2001 From: Karl Pierce Date: Thu, 20 Aug 2020 08:47:34 -0700 Subject: [PATCH 4/5] Correct guarded unit tests to be more relevant --- tests/ModelTest.php | 20 ++++++++++++++++++-- tests/models/Guarded.php | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/ModelTest.php b/tests/ModelTest.php index c4a2cf661..2e25a9a58 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -726,8 +726,24 @@ public function testTruncateModel() public function testGuardedModel() { - Guarded::create(['var' => 'val']); + $model = new Guarded(); - $this->assertEquals(1, Guarded::count()); + // foobar is properly guarded + $model->fill(['foobar' => 'ignored', 'name' => 'John Doe']); + $this->assertFalse(isset($model->foobar)); + $this->assertSame('John Doe', $model->name); + + // foobar is guarded to any level + $model->fill(['foobar->level2' => 'v2']); + $this->assertNull($model->getAttribute('foobar->level2')); + + // multi level statement also guarded + $model->fill(['level1->level2' => 'v1']); + $this->assertNull($model->getAttribute('level1->level2')); + + // level1 is still writable + $dataValues = ['array', 'of', 'values']; + $model->fill(['level1' => $dataValues]); + $this->assertEquals($dataValues, $model->getAttribute('level1')); } } diff --git a/tests/models/Guarded.php b/tests/models/Guarded.php index 4d2a3a617..8f6b6d58c 100644 --- a/tests/models/Guarded.php +++ b/tests/models/Guarded.php @@ -7,5 +7,5 @@ class Guarded extends Eloquent { protected $connection = 'mongodb'; protected $collection = 'guarded'; - protected $guarded = ['foobar']; + protected $guarded = ['foobar', 'level1->level2']; } From 2a8c2fd16b586fd66b1f216cfe939e2e8c616b10 Mon Sep 17 00:00:00 2001 From: Karl Pierce Date: Thu, 20 Aug 2020 09:03:30 -0700 Subject: [PATCH 5/5] Update readme to document guarding attributes --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 372e2dc6a..56256fea5 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ This package adds functionalities to the Eloquent model and Query builder for Mo - [Extending the base model](#extending-the-base-model) - [Soft Deletes](#soft-deletes) - [Dates](#dates) + - [Guarding attributes](#guarding-attributes) - [Basic Usage](#basic-usage) - [MongoDB-specific operators](#mongodb-specific-operators) - [MongoDB-specific Geo operations](#mongodb-specific-geo-operations) @@ -240,7 +241,7 @@ use Jenssegers\Mongodb\Auth\User as Authenticatable; class User extends Authenticatable { - + } ``` @@ -263,6 +264,13 @@ class User extends Model For more information check [Laravel Docs about Soft Deleting](http://laravel.com/docs/eloquent#soft-deleting). +### Guarding attributes + +When choosing between guarding attributes or marking some as fillable, Taylor Otwell prefers the fillable route. +This is in light of [recent security issues described here](https://blog.laravel.com/security-release-laravel-61835-7240). + +Keep in mind guarding still works, but you may experience unexpected behavior. + ### Dates Eloquent allows you to work with Carbon or DateTime objects instead of MongoDate objects. Internally, these dates will be converted to MongoDate objects when saved to the database.