Skip to content

Commit

Permalink
Merge pull request #1132 from firebase/jhuleatt-firestore-auth-context
Browse files Browse the repository at this point in the history
Add samples for Firestore with Auth context
  • Loading branch information
blidd-google committed Apr 9, 2024
2 parents a8b1ab8 + 508bf90 commit 071ac15
Show file tree
Hide file tree
Showing 15 changed files with 470 additions and 113 deletions.
65 changes: 65 additions & 0 deletions Node/quickstarts/firestore-sync-auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log*

# Firebase cache
.firebase/

# Firebase config

# Uncomment this if you'd like others to create their own Firebase project.
# For a team working on the same Firebase project(s), it is recommended to leave
# it commented so all members can deploy to the same project(s) in .firebaserc.
# .firebaserc

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
70 changes: 70 additions & 0 deletions Node/quickstarts/firestore-sync-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Firebase SDK for Cloud Functions Quickstart - Firestore with auth context

This quickstart demonstrates using the **Firebase SDK for Cloud Functions** with
**Firestore** with authentication context.

## Introduction

This sample app adds auth metadata to all documents written to a collection.

## Set up the sample

Before you can test the functions locally or deploy to a Firebase project,
you'll need to run `npm install` in the `functions` directory.

## Run locally with the Firebase Emulator suite

The
[Firebase Local Emulator Suite](https://firebase.google.com/docs/emulator-suite)
allows you to build and test apps on your local machine instead of deploying to
a Firebase project.

1. Create a Firebase project in the
[Firebase Console](https://console.firebase.google.com)
> _Wondering why this step is needed?_ Even though the emulator will run this
> sample on your local machine, it needs to interact with a Firebase project
> to retrieve some configuration values.
1. [Set up or update the Firebase CLI](https://firebase.google.com/docs/cli#setup_update_cli)
1. Run `firebase emulators:start`
1. Open the Emulator Suite UI
1. Look in the output of the `firebase emulators:start` command for the URL
of the Emulator Suite UI. It defaults to
[localhost:4000](http://localhost:4000), but may be hosted on a different
port on your machine.
1. Enter that URL in your browser to open the UI.
1. Trigger the functions
1. Look in the output of the `firebase emulators:start` command for the URL
of the http function "verifyComment". It will look similar to:
`http://localhost:5001/MY_PROJECT/us-central1/verifyComment`
1. `MY_PROJECT` will be replaced with your project ID
1. The port may be different on your local machine
1. Create a new document in the `comments` collection in Firestore in the emulator UI.
1. View the effects of the functions in the Emulator Suite UI

1. In the "Logs" tab, you should see new logs indicating that the functions
"verifyComment" and "makeuppercase" ran:

> `functions: Beginning execution of "verifyComment"`
1. In the "Firestore" tab, you should see the document containing your original
message updated to include auth context.

## Deploy and test on a live Firebase project

To deploy and test the sample:

1. Create a Firebase project on the
[Firebase Console](https://console.firebase.google.com)
1. Deploy your project's code using `firebase deploy`
1. Create a new document in the `comments` collection in Firestore in the Firebase console.

You should see the document containing your original message updated to include auth context.

## Contributing

We'd love that you contribute to the project. Before doing so please read our
[Contributor guide](../../CONTRIBUTING.md).

## License

© Google, 2023. Licensed under an [Apache-2](../../LICENSE) license.
20 changes: 20 additions & 0 deletions Node/quickstarts/firestore-sync-auth/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"functions": {
"codebase": "firestore-sync-auth"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"emulators": {
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"ui": {
"enabled": true
}
}
}
4 changes: 4 additions & 0 deletions Node/quickstarts/firestore-sync-auth/firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"indexes": [],
"fieldOverrides": []
}
8 changes: 8 additions & 0 deletions Node/quickstarts/firestore-sync-auth/firestore.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
service cloud.firestore {
match /databases/{database}/documents {
match /comments/{comment} {
// Allow authenticated users to read/write the comments collection
allow read, write: if request.auth != null;
}
}
}
30 changes: 30 additions & 0 deletions Node/quickstarts/firestore-sync-auth/functions/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright 2023 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.
*/

module.exports = {
root: true,
env: {
es2020: true,
node: true,
},
extends: [
"eslint:recommended",
"google",
],
rules: {
quotes: ["error", "double"],
},
};
1 change: 1 addition & 0 deletions Node/quickstarts/firestore-sync-auth/functions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
60 changes: 60 additions & 0 deletions Node/quickstarts/firestore-sync-auth/functions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Copyright 2023 Google Inc. All Rights Reserved.
*
* 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.
*/
"use strict";

// [START all]
// [START import]
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {
onDocumentWrittenWithAuthContext,
} = require("firebase-functions/v2/firestore");
const {logger} = require("firebase-functions");

exports.verifyComment = onDocumentWrittenWithAuthContext(
"comments/{commentId}",
(event) => {
const snapshot = event.data.after;
if (!snapshot) {
logger.log("No data associated with the event");
return;
}

// retrieve auth context from event
const {authType, authId} = event;

let verified = false;
if (authType === "system") {
// system-generated users are automatically verified
verified = true;
} else if (authType === "unknown" || authType === "unauthenticated") {
// admin users from a specific domain are verified
if (authId.endsWith("@example.com")) {
verified = true;
}
}

// add auth medadata to the document
return snapshot.ref.set(
{
created_by: authId ?? "undefined",
verified,
},
{merge: true},
);
},
);

// [END all]
28 changes: 28 additions & 0 deletions Node/quickstarts/firestore-sync-auth/functions/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "firestore-sync-auth",
"description": "Cloud Functions for Firebase",
"dependencies": {
"firebase-admin": "^11.9.0",
"firebase-functions": "^4.9.0"
},
"devDependencies": {
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"eslint": "^8.40.0",
"mocha": "^7.2.0",
"sinon": "^9.2.4"
},
"scripts": {
"lint": "./node_modules/.bin/eslint --max-warnings=0 .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log",
"compile": "cp ../../../../tsconfig.template.json ./tsconfig-compile.json && tsc --project tsconfig-compile.json"
},
"engines": {
"node": "18"
},
"private": true
}
1 change: 1 addition & 0 deletions Python/quickstarts/firestore-sync-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# uppercase-firestore
5 changes: 5 additions & 0 deletions Python/quickstarts/firestore-sync-auth/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"functions": {
"codebase": "firestore-sync-auth"
}
}
43 changes: 43 additions & 0 deletions Python/quickstarts/firestore-sync-auth/functions/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2023 Google Inc. All Rights Reserved.
#
# 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 all]
from firebase_functions import firestore_fn


# [START verifyComment]
@firestore_fn.on_document_updated_with_auth_context(document="comments/{comment_id}")
def verify_comment(event: Event[Change[DocumentSnapshot]]) -> None:

# Get the current and previous document values.
new_value = event.data.after
prev_value = event.data.before

# Get the auth context from the event
user_auth_type = event.auth_type
user_auth_id = event.auth_id

verified = False
if user_auth_type == "system":
# system-generated users are automatically verified
verified = True
elif user_auth_type in ("unknown", "unauthenticated"):
if user_auth_id.endswith("@example.com"):
# admin users from a specific domain are verified
verified = True

# add auth medadata to the document
new_value.reference.update({"created_by": user_auth_id, "verified": verified})
# [END verifyComment]
# [END all]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
firebase-functions
firebase-admin
Loading

0 comments on commit 071ac15

Please sign in to comment.