Skip to content

Commit

Permalink
Introduce database rule sets
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromegamez committed Nov 25, 2017
1 parent 2126750 commit c2128d6
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 26 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Unreleased

* Add support for getting and updating Realtime Database Rules
([#136](https://github.com/kreait/firebase-php/pull/136))
([#136](https://github.com/kreait/firebase-php/pull/136))
([Documentation](https://firebase-php.readthedocs.io/en/latest/realtime-database.html#database-rules))

## 3.4.2 - 2017-11-08

Expand Down
38 changes: 33 additions & 5 deletions docs/realtime-database.rst
Original file line number Diff line number Diff line change
Expand Up @@ -378,17 +378,45 @@ includes the sent request and the received response object:
}
******************
Security and Rules
******************
**************
Database rules
**************

Learn more about the usage of Firebase Realtime Database Rules in the
`official documentation <https://firebase.google.com/docs/database/security/>`_.

.. code-block:: php
$rules = $db->getRules();
$db->setRules($rules);
use Kreait\Firebase\Database\RuleSet;
// The default rules allow full read and write access to authenticated users of your app
$ruleSet = RuleSet::default();
// This level of access means anyone can read or write to your database. You should
// configure more secure rules before launching your app.
$ruleSet = RuleSet::public();
// Private rules disable read and write access to your database by users.
// With these rules, you can only access the database through the
// Firebase console and the Admin SDKs.
$ruleSet = RuleSet::private();
// You can of course define custom rules
$ruleSet = RuleSet::fromArray(['rules' => [
'.read' => true,
'.write' => false,
'users' => [
'$uid' => [
'.read' => '$uid === auth.uid',
'.write' => '$uid === auth.uid',
]
]
]]);
$db->updateRules($ruleSet);
$freshRuleSet = $db->getRules(); // Returns a new RuleSet instance
$actualRules = $ruleSet->getRules(); // returns an array
.. rubric:: Footnotes
Expand Down
25 changes: 9 additions & 16 deletions src/Firebase/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
use GuzzleHttp\Psr7;
use Kreait\Firebase\Database\ApiClient;
use Kreait\Firebase\Database\Reference;
use Kreait\Firebase\Database\RuleSet;
use Kreait\Firebase\Exception\ApiException;
use Kreait\Firebase\Exception\InvalidArgumentException;
use Kreait\Firebase\Exception\InvalidDatabaseRuleSet;
use Kreait\Firebase\Exception\OutOfRangeException;
use Psr\Http\Message\UriInterface;

Expand Down Expand Up @@ -109,34 +112,24 @@ public function getReferenceFromUrl($uri): Reference
*
* @see https://firebase.google.com/docs/database/rest/app-management#retrieving-firebase-realtime-database-rules
*
* @return array
* @return RuleSet
*/
public function getRules(): array
public function getRules(): RuleSet
{
$rules = $this->client->get($this->uri->withPath('.settings/rules'));

return $rules ?: [];
return RuleSet::fromArray($rules);
}

/**
* Update Firebase Database Rules.
*
* @see https://firebase.google.com/docs/database/rest/app-management#updating-firebase-realtime-database-rules
*
* @param array $rules
*
* @throws InvalidArgumentException If rules are invalid
*
* @return Database
* @param RuleSet $ruleSet
*/
public function setRules(array $rules): self
public function updateRules(RuleSet $ruleSet)
{
try {
$this->client->set($this->uri->withPath('.settings/rules'), $rules);
} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode());
}

return $this;
$this->client->set($this->uri->withPath('.settings/rules'), $ruleSet);
}
}
98 changes: 98 additions & 0 deletions src/Firebase/Database/RuleSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace Kreait\Firebase\Database;

use JsonSerializable;

class RuleSet implements JsonSerializable
{
/**
* @var array
*/
private $rules;

private function __construct(array $rules)
{
if (!array_key_exists('rules', $rules)) {
$rules = ['rules' => $rules];
}

$this->rules = $rules;
}

/**
* The default rules require Authentication. They allow full read and write access
* to authenticated users of your app. They are useful if you want data open to
* all users of your app but don't want it open to the world.
*
* @see https://firebase.google.com/docs/database/security/quickstart#sample-rules
*
* @return self
*/
public static function default(): self
{
return new self([
'rules' => [
'.read' => 'auth != null',
'.write' => 'auth != null',
],
]);
}

/**
* During development, you can use the public rules in place of the default rules to set
* your files publicly readable and writable. This can be useful for prototyping,
* as you can get started without setting up Authentication.
*
* This level of access means anyone can read or write to your database. You should
* configure more secure rules before launching your app.
*
* @see https://firebase.google.com/docs/database/security/quickstart#sample-rules
*
* @return self
*/
public static function public(): self
{
return new self([
'rules' => [
'.read' => true,
'.write' => true,
],
]);
}

/**
* Private rules disable read and write access to your database by users. With these rules,
* you can only access the database through the Firebase console and an Admin SDK.
*
* @see https://firebase.google.com/docs/database/security/quickstart#sample-rules
*
* @return self
*/
public static function private(): self
{
return new self([
'rules' => [
'.read' => false,
'.write' => false,
],
]);
}

public static function fromArray(array $rules): self
{
return new self($rules);
}

public function getRules(): array
{
return $this->rules;
}

public function jsonSerialize()
{
return $this->rules;
}
}
14 changes: 10 additions & 4 deletions tests/Firebase/DatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Kreait\Firebase\Database;
use Kreait\Firebase\Database\ApiClient;
use Kreait\Firebase\Database\Reference;
use Kreait\Firebase\Database\RuleSet;
use Kreait\Firebase\Exception\InvalidArgumentException;
use Kreait\Firebase\Http\Auth;
use Kreait\Tests\FirebaseTestCase;
Expand Down Expand Up @@ -81,17 +82,22 @@ public function testGetRules()
{
$this->apiClient->expects($this->once())
->method('get')
->with($this->uri->withPath('.settings/rules'));
->with($this->uri->withPath('.settings/rules'))
->willReturn($expected = RuleSet::default()->getRules());

$this->assertEquals($this->database->getRules(), []);
$ruleSet = $this->database->getRules();

$this->assertEquals($expected, $ruleSet->getRules());
}

public function testSetRules()
{
$ruleSet = RuleSet::default();

$this->apiClient->expects($this->once())
->method('set')
->with($this->uri->withPath('.settings/rules'));
->with($this->uri->withPath('.settings/rules'), $ruleSet);

$this->assertEquals($this->database->setRules([]), $this->database);
$this->database->updateRules($ruleSet);
}
}

0 comments on commit c2128d6

Please sign in to comment.