Skip to content

Commit 071ac15

Browse files
authored
Merge pull request #1132 from firebase/jhuleatt-firestore-auth-context
Add samples for Firestore with Auth context
2 parents a8b1ab8 + 508bf90 commit 071ac15

File tree

15 files changed

+470
-113
lines changed

15 files changed

+470
-113
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
firebase-debug.log*
8+
9+
# Firebase cache
10+
.firebase/
11+
12+
# Firebase config
13+
14+
# Uncomment this if you'd like others to create their own Firebase project.
15+
# For a team working on the same Firebase project(s), it is recommended to leave
16+
# it commented so all members can deploy to the same project(s) in .firebaserc.
17+
# .firebaserc
18+
19+
# Runtime data
20+
pids
21+
*.pid
22+
*.seed
23+
*.pid.lock
24+
25+
# Directory for instrumented libs generated by jscoverage/JSCover
26+
lib-cov
27+
28+
# Coverage directory used by tools like istanbul
29+
coverage
30+
31+
# nyc test coverage
32+
.nyc_output
33+
34+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
35+
.grunt
36+
37+
# Bower dependency directory (https://bower.io/)
38+
bower_components
39+
40+
# node-waf configuration
41+
.lock-wscript
42+
43+
# Compiled binary addons (http://nodejs.org/api/addons.html)
44+
build/Release
45+
46+
# Dependency directories
47+
node_modules/
48+
49+
# Optional npm cache directory
50+
.npm
51+
52+
# Optional eslint cache
53+
.eslintcache
54+
55+
# Optional REPL history
56+
.node_repl_history
57+
58+
# Output of 'npm pack'
59+
*.tgz
60+
61+
# Yarn Integrity file
62+
.yarn-integrity
63+
64+
# dotenv environment variables file
65+
.env
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Firebase SDK for Cloud Functions Quickstart - Firestore with auth context
2+
3+
This quickstart demonstrates using the **Firebase SDK for Cloud Functions** with
4+
**Firestore** with authentication context.
5+
6+
## Introduction
7+
8+
This sample app adds auth metadata to all documents written to a collection.
9+
10+
## Set up the sample
11+
12+
Before you can test the functions locally or deploy to a Firebase project,
13+
you'll need to run `npm install` in the `functions` directory.
14+
15+
## Run locally with the Firebase Emulator suite
16+
17+
The
18+
[Firebase Local Emulator Suite](https://firebase.google.com/docs/emulator-suite)
19+
allows you to build and test apps on your local machine instead of deploying to
20+
a Firebase project.
21+
22+
1. Create a Firebase project in the
23+
[Firebase Console](https://console.firebase.google.com)
24+
> _Wondering why this step is needed?_ Even though the emulator will run this
25+
> sample on your local machine, it needs to interact with a Firebase project
26+
> to retrieve some configuration values.
27+
1. [Set up or update the Firebase CLI](https://firebase.google.com/docs/cli#setup_update_cli)
28+
1. Run `firebase emulators:start`
29+
1. Open the Emulator Suite UI
30+
1. Look in the output of the `firebase emulators:start` command for the URL
31+
of the Emulator Suite UI. It defaults to
32+
[localhost:4000](http://localhost:4000), but may be hosted on a different
33+
port on your machine.
34+
1. Enter that URL in your browser to open the UI.
35+
1. Trigger the functions
36+
1. Look in the output of the `firebase emulators:start` command for the URL
37+
of the http function "verifyComment". It will look similar to:
38+
`http://localhost:5001/MY_PROJECT/us-central1/verifyComment`
39+
1. `MY_PROJECT` will be replaced with your project ID
40+
1. The port may be different on your local machine
41+
1. Create a new document in the `comments` collection in Firestore in the emulator UI.
42+
1. View the effects of the functions in the Emulator Suite UI
43+
44+
1. In the "Logs" tab, you should see new logs indicating that the functions
45+
"verifyComment" and "makeuppercase" ran:
46+
47+
> `functions: Beginning execution of "verifyComment"`
48+
49+
1. In the "Firestore" tab, you should see the document containing your original
50+
message updated to include auth context.
51+
52+
## Deploy and test on a live Firebase project
53+
54+
To deploy and test the sample:
55+
56+
1. Create a Firebase project on the
57+
[Firebase Console](https://console.firebase.google.com)
58+
1. Deploy your project's code using `firebase deploy`
59+
1. Create a new document in the `comments` collection in Firestore in the Firebase console.
60+
61+
You should see the document containing your original message updated to include auth context.
62+
63+
## Contributing
64+
65+
We'd love that you contribute to the project. Before doing so please read our
66+
[Contributor guide](../../CONTRIBUTING.md).
67+
68+
## License
69+
70+
© Google, 2023. Licensed under an [Apache-2](../../LICENSE) license.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"functions": {
3+
"codebase": "firestore-sync-auth"
4+
},
5+
"firestore": {
6+
"rules": "firestore.rules",
7+
"indexes": "firestore.indexes.json"
8+
},
9+
"emulators": {
10+
"functions": {
11+
"port": 5001
12+
},
13+
"firestore": {
14+
"port": 8080
15+
},
16+
"ui": {
17+
"enabled": true
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"indexes": [],
3+
"fieldOverrides": []
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
service cloud.firestore {
2+
match /databases/{database}/documents {
3+
match /comments/{comment} {
4+
// Allow authenticated users to read/write the comments collection
5+
allow read, write: if request.auth != null;
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
module.exports = {
18+
root: true,
19+
env: {
20+
es2020: true,
21+
node: true,
22+
},
23+
extends: [
24+
"eslint:recommended",
25+
"google",
26+
],
27+
rules: {
28+
quotes: ["error", "double"],
29+
},
30+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Copyright 2023 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the 'License');
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an 'AS IS' BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
"use strict";
17+
18+
// [START all]
19+
// [START import]
20+
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
21+
const {
22+
onDocumentWrittenWithAuthContext,
23+
} = require("firebase-functions/v2/firestore");
24+
const {logger} = require("firebase-functions");
25+
26+
exports.verifyComment = onDocumentWrittenWithAuthContext(
27+
"comments/{commentId}",
28+
(event) => {
29+
const snapshot = event.data.after;
30+
if (!snapshot) {
31+
logger.log("No data associated with the event");
32+
return;
33+
}
34+
35+
// retrieve auth context from event
36+
const {authType, authId} = event;
37+
38+
let verified = false;
39+
if (authType === "system") {
40+
// system-generated users are automatically verified
41+
verified = true;
42+
} else if (authType === "unknown" || authType === "unauthenticated") {
43+
// admin users from a specific domain are verified
44+
if (authId.endsWith("@example.com")) {
45+
verified = true;
46+
}
47+
}
48+
49+
// add auth medadata to the document
50+
return snapshot.ref.set(
51+
{
52+
created_by: authId ?? "undefined",
53+
verified,
54+
},
55+
{merge: true},
56+
);
57+
},
58+
);
59+
60+
// [END all]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "firestore-sync-auth",
3+
"description": "Cloud Functions for Firebase",
4+
"dependencies": {
5+
"firebase-admin": "^11.9.0",
6+
"firebase-functions": "^4.9.0"
7+
},
8+
"devDependencies": {
9+
"chai": "^4.3.6",
10+
"chai-as-promised": "^7.1.1",
11+
"eslint": "^8.40.0",
12+
"mocha": "^7.2.0",
13+
"sinon": "^9.2.4"
14+
},
15+
"scripts": {
16+
"lint": "./node_modules/.bin/eslint --max-warnings=0 .",
17+
"serve": "firebase emulators:start --only functions",
18+
"shell": "firebase functions:shell",
19+
"start": "npm run shell",
20+
"deploy": "firebase deploy --only functions",
21+
"logs": "firebase functions:log",
22+
"compile": "cp ../../../../tsconfig.template.json ./tsconfig-compile.json && tsc --project tsconfig-compile.json"
23+
},
24+
"engines": {
25+
"node": "18"
26+
},
27+
"private": true
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# uppercase-firestore
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"functions": {
3+
"codebase": "firestore-sync-auth"
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2023 Google Inc. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START all]
16+
from firebase_functions import firestore_fn
17+
18+
19+
# [START verifyComment]
20+
@firestore_fn.on_document_updated_with_auth_context(document="comments/{comment_id}")
21+
def verify_comment(event: Event[Change[DocumentSnapshot]]) -> None:
22+
23+
# Get the current and previous document values.
24+
new_value = event.data.after
25+
prev_value = event.data.before
26+
27+
# Get the auth context from the event
28+
user_auth_type = event.auth_type
29+
user_auth_id = event.auth_id
30+
31+
verified = False
32+
if user_auth_type == "system":
33+
# system-generated users are automatically verified
34+
verified = True
35+
elif user_auth_type in ("unknown", "unauthenticated"):
36+
if user_auth_id.endswith("@example.com"):
37+
# admin users from a specific domain are verified
38+
verified = True
39+
40+
# add auth medadata to the document
41+
new_value.reference.update({"created_by": user_auth_id, "verified": verified})
42+
# [END verifyComment]
43+
# [END all]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
firebase-functions
2+
firebase-admin

0 commit comments

Comments
 (0)