Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions functions/firebase_auth/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"require": {
"google/cloud-functions-framework": "^0.7.1"
},
"scripts": {
"start": [
"Composer\\Config::disableProcessTimeout",
"FUNCTION_SIGNATURE_TYPE=cloudevent FUNCTION_TARGET=firebaseAuth php -S localhost:${PORT:-8080} vendor/bin/router.php"
]
},
"require-dev": {
"google/auth": "^1.14",
"google/cloud-logging": "^1.21"
}
}
37 changes: 37 additions & 0 deletions functions/firebase_auth/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/**
* Copyright 2021 Google LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// [START functions_firebase_auth]

use Google\CloudFunctions\CloudEvent;

function firebaseAuth(CloudEvent $cloudevent)
{
$log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
$data = $cloudevent->getData();

fwrite(
$log,
'Function triggered by change to user: ' . $data['uid'] . PHP_EOL
);
fwrite($log, 'Created at: ' . $data['metadata']['createTime'] . PHP_EOL);

if (isset($data['email'])) {
fwrite($log, 'Email: ' . $data['email'] . PHP_EOL);
}
}
// [END functions_firebase_auth]
34 changes: 34 additions & 0 deletions functions/firebase_auth/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2021 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<phpunit bootstrap="../../testing/bootstrap.php" convertWarningsToExceptions="false">
<testsuites>
<testsuite name="Cloud Functions Firebase Auth Test Suite">
<directory>test</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<filter>
<whitelist>
<directory suffix=".php">.</directory>
<exclude>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
150 changes: 150 additions & 0 deletions functions/firebase_auth/test/DeployTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php
/**
* Copyright 2021 Google LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Google\Cloud\Samples\Functions\FirebaseAuth\Test;

use Google\Auth\ApplicationDefaultCredentials;
use Google\Auth\CredentialsLoader;
use Google\Cloud\Logging\LoggingClient;
use Google\Cloud\TestUtils\CloudFunctionDeploymentTrait;
use Google\Cloud\TestUtils\EventuallyConsistentTestTrait;
use PHPUnit\Framework\TestCase;

/**
* Class DeployTest.
* @group deploy
*
* This test is not run by the CI system.
*
* To skip deployment of a new function, run with "GOOGLE_SKIP_DEPLOYMENT=true".
* To skip deletion of the tested function, run with "GOOGLE_KEEP_DEPLOYMENT=true".
*/
class DeployTest extends TestCase
{
use CloudFunctionDeploymentTrait;
use EventuallyConsistentTestTrait;

/** @var string */
private static $entryPoint = 'firebaseAuth';

/** @var string */
private static $functionSignatureType = 'cloudevent';

/** @var LoggingClient */
private static $loggingClient;

/** @var \GuzzleHttp\Client */
private static $apiHttpClient;

/**
* Deploy the Cloud Function, called from DeploymentTrait::deployApp().
*
* Overrides CloudFunctionDeploymentTrait::doDeploy().
*/
private static function doDeploy()
{
$event = 'providers/firebase.auth/eventTypes/user.create';

return self::$fn->deploy([
'--trigger-event' => $event
], '');
}

public function dataProvider()
{
$email = uniqid();
return [
[
'label' => 'Listens to Auth events',
'email' => $email . '@example.com',
'expected' => $email . '@example.com'
]
];
}

/**
* @dataProvider dataProvider
*/
public function testFirebaseAuth(
string $label,
string $email,
string $expected
): void {
// Trigger user creation.
$this->createAuthUser($email);

// Give event and log systems a head start.
// If log retrieval fails to find logs for our function within retry limit, increase sleep time.
sleep(10);

$fiveMinAgo = date(\DateTime::RFC3339, strtotime('-5 minutes'));
$this->processFunctionLogs($fiveMinAgo, function (\Iterator $logs) use ($expected, $label) {
// Concatenate all relevant log messages.
$actual = '';
foreach ($logs as $log) {
$info = $log->info();
if (isset($info['textPayload'])) {
$actual .= $info['textPayload'];
}
}

// Only testing one property to decrease odds the expected logs are
// split between log requests.
$this->assertStringContainsString($expected, $actual, $label);
});
}

/**
* Create a new Firebase Auth user.
*
* @param string $email The key to update.
* @param string $value The value to set the key to.
*
* @throws \RuntimeException
*/
private function createAuthUser(string $email): void
{
if (empty(self::$apiHttpClient)) {
$credentials = ApplicationDefaultCredentials::getCredentials('https://www.googleapis.com/auth/cloud-platform');
self::$apiHttpClient = CredentialsLoader::makeHttpClient($credentials, [
'base_uri' => 'https://identitytoolkit.googleapis.com/'
]);
}

// Create the account
$createResponse = (string) self::$apiHttpClient->post('/v1/accounts:signUp', [
'headers' => ['If-Match' => '*'],
'json' => [
'email' => $email,
'password' => uniqid(),
'returnSecureToken' => true
]
])->getBody();

$idToken = json_decode($createResponse, true)['localId'];

// Delete the account (to clean up after the test)
self::$apiHttpClient->post('/v1/accounts:delete', [
'headers' => ['If-Match' => '*'],
'json' => [
'localId' => $idToken
]
]);
}
}
84 changes: 84 additions & 0 deletions functions/firebase_auth/test/IntegrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
/**
* Copyright 2021 Google LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Google\Cloud\Samples\Functions\FirebaseAuth\Test;

use PHPUnit\Framework\TestCase;
use Google\CloudFunctions\CloudEvent;
use Google\Cloud\TestUtils\CloudFunctionLocalTestTrait;

/**
* Class IntegrationTest.
*
* Integration Test for firebaseAuth.
*/
class IntegrationTest extends TestCase
{
use CloudFunctionLocalTestTrait;

/** @var string */
private static $entryPoint = 'firebaseAuth';

/** @var string */
private static $functionSignatureType = 'cloudevent';

public function dataProvider()
{
return [
[
'cloudevent' => CloudEvent::fromArray([
'id' => uniqid(),
'source' => 'firebase.googleapis.com',
'specversion' => '1.0',
'type' => 'google.firebase.auth.user.v1.created',
'data' => [
'uid' => 'me',
'email' => '[email protected]',
'metadata' => ['createdAt' => date('c')],
],
]),
'statusCode' => '200',
],
];
}

/**
* @dataProvider dataProvider
*/
public function testFirebaseRemoteConfig(
CloudEvent $cloudevent,
string $statusCode
): void {
// Send an HTTP request using CloudEvent.
$resp = $this->request($cloudevent);

// The Cloud Function logs all data to stderr.
$actual = self::$localhost->getIncrementalErrorOutput();

// Confirm the status code.
$this->assertEquals($statusCode, $resp->getStatusCode());

// Verify the data properties are logged by the function.
foreach ($cloudevent->getData() as $property => $value) {
if (is_string($value)) {
$this->assertStringContainsString($value, $actual);
}
}
}
}