Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invitation Code Verification Module #32

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
19bf2f3
Impl `InvitationCodeVerifier`
MatthewTurk247 May 23, 2024
67e124b
Remove extraneous lines
MatthewTurk247 May 24, 2024
fc583c9
Merge option
MatthewTurk247 May 24, 2024
99be22a
Remove extraneous lines
MatthewTurk247 May 24, 2024
45516bd
Update license headers
MatthewTurk247 May 24, 2024
3b9d97e
Setting up linter
MatthewTurk247 May 25, 2024
deca8ff
Add JSDoc comments
MatthewTurk247 May 25, 2024
6ed977f
Minor refactoring
MatthewTurk247 May 25, 2024
7c71871
Linting
MatthewTurk247 May 25, 2024
986e24f
Update license headers
MatthewTurk247 May 25, 2024
e6ac4af
Remove `firestore` param from constructor
MatthewTurk247 May 25, 2024
14c5e6f
Skeleton test setup
MatthewTurk247 May 26, 2024
864eaab
Might need multiple invitation codes
MatthewTurk247 May 26, 2024
4cc4a1c
Reordering tests
MatthewTurk247 May 26, 2024
c8efe1a
Further reordering
MatthewTurk247 May 26, 2024
d212e43
Tests successful
MatthewTurk247 May 26, 2024
12d41ac
Remove extraneous lines
MatthewTurk247 May 26, 2024
29924ca
Add license files
MatthewTurk247 May 26, 2024
8b6ad2a
Add license for `firebase` folder
MatthewTurk247 May 26, 2024
7155f49
Fixed typo
MatthewTurk247 May 26, 2024
7c5e671
Fixed another typo
MatthewTurk247 May 26, 2024
412d5e3
Update spezi-invitation-code/firebase.json
MatthewTurk247 May 28, 2024
9fa7e76
Remove storage from Firebase configuration
MatthewTurk247 May 28, 2024
ac67738
Remove storage from Firebase rules
MatthewTurk247 May 28, 2024
54ffb7f
Update license headers
MatthewTurk247 May 28, 2024
6934a9c
Remove storage from rules
MatthewTurk247 May 30, 2024
c106269
Remove leftover files
MatthewTurk247 May 30, 2024
2dfbe80
Merge branch 'main' into invitation-codes
PSchmiedmayer May 31, 2024
ce1c46a
Separating tests
MatthewTurk247 May 31, 2024
da6ec17
More separation of tests
MatthewTurk247 May 31, 2024
91e8714
More separation of tests
MatthewTurk247 May 31, 2024
26a6519
Tests are looking good so far
MatthewTurk247 May 31, 2024
dbd53d0
Improved tests
MatthewTurk247 May 31, 2024
15c14e9
Remove leftover lines
MatthewTurk247 May 31, 2024
365b4d4
Remove unnecessary `async` markers
MatthewTurk247 May 31, 2024
6adea61
Improve teardown code
MatthewTurk247 Jun 1, 2024
d041293
Found `https.CallableRequest` definition
MatthewTurk247 Jun 3, 2024
82aa6be
Fixed typo
MatthewTurk247 Jun 3, 2024
058b1ab
GitHub Actions for JS tests
MatthewTurk247 Jun 4, 2024
06596cb
Specify working directory
MatthewTurk247 Jun 4, 2024
2ceeb21
Specify working directory
MatthewTurk247 Jun 4, 2024
a9472c1
Setting path for JS tests
MatthewTurk247 Jun 4, 2024
e0c7073
Basic steps for `testandcoverage`
MatthewTurk247 Jun 4, 2024
7dd6fb9
Fixed typos
MatthewTurk247 Jun 4, 2024
31dd937
Trying again
MatthewTurk247 Jun 4, 2024
6dc5df2
Try again to get GitHub Actions working
MatthewTurk247 Jun 4, 2024
f3be790
Trying `cd` now
MatthewTurk247 Jun 4, 2024
ae88231
Navigate to proper directory
MatthewTurk247 Jun 5, 2024
717bcc4
Try working directory again
MatthewTurk247 Jun 5, 2024
0cdfe52
Set defaults for working directory
MatthewTurk247 Jun 5, 2024
0565122
Merge branch 'main' into invitation-codes
MatthewTurk247 Jun 13, 2024
cf863d6
Pass in working directory
MatthewTurk247 Jun 13, 2024
8fbbdf0
Update build-and-test.yml
PSchmiedmayer Jun 13, 2024
22353b0
Update build-and-test.yml
PSchmiedmayer Jun 13, 2024
8e6b624
Update build-and-test.yml
PSchmiedmayer Jun 13, 2024
5c793c0
Update Setup
PSchmiedmayer Jun 13, 2024
8405eb1
New documentation, including diagram
MatthewTurk247 Jun 13, 2024
d7d0701
Adjustments to syntax
MatthewTurk247 Jun 13, 2024
6f29861
Missed a line
MatthewTurk247 Jun 13, 2024
613cc30
Additional documentation
MatthewTurk247 Jun 13, 2024
f9dd48c
More documentation
MatthewTurk247 Jun 13, 2024
f02449d
Is `admin.initializeApp()` necessary in the tests?
MatthewTurk247 Jun 13, 2024
a337b4e
`initializeApp` is back
MatthewTurk247 Jun 13, 2024
ec6a24d
Update license headers
MatthewTurk247 Jun 13, 2024
7527b0d
Update license headers
MatthewTurk247 Jun 13, 2024
1e08db5
Update license headers
MatthewTurk247 Jun 13, 2024
f812eb0
Load in credentials
MatthewTurk247 Jun 14, 2024
16f2fcd
Update build-and-test.yml
PSchmiedmayer Jun 15, 2024
ebd0a1d
Load in `GOOGLE_APPLICATION_CREDENTIALS_BASE64`
MatthewTurk247 Jun 15, 2024
cc14034
Will try loading credentials again
MatthewTurk247 Jun 15, 2024
6012cf4
Next attempt
MatthewTurk247 Jun 15, 2024
3a0dd97
Next attempt
MatthewTurk247 Jun 15, 2024
8384a19
Set env
MatthewTurk247 Jun 15, 2024
7f49d7b
Next attempt
MatthewTurk247 Jun 15, 2024
cc53296
Next attempt
MatthewTurk247 Jun 15, 2024
a85c06d
Inspect length of string
MatthewTurk247 Jun 15, 2024
b72c219
Inspect length of string
MatthewTurk247 Jun 15, 2024
0b50b2f
Does not seem like `GOOGLE_APPLICATION_CREDENTIALS_BASE64` is loading in
MatthewTurk247 Jun 15, 2024
7cdcb6e
Trying that again with modified script
MatthewTurk247 Jun 15, 2024
a52dc46
Next attempt
MatthewTurk247 Jun 15, 2024
4987d67
Next attempt
MatthewTurk247 Jun 15, 2024
fc641ce
Next attempt
MatthewTurk247 Jun 15, 2024
aeb9651
Next attempt
MatthewTurk247 Jun 15, 2024
0d4229c
Next attempt
MatthewTurk247 Jun 15, 2024
82cfa37
Next attempt
MatthewTurk247 Jun 15, 2024
ef4dccf
Require credentials
MatthewTurk247 Jun 15, 2024
3403246
Require credentials
MatthewTurk247 Jun 15, 2024
49fccef
Require credentials
MatthewTurk247 Jun 15, 2024
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
24 changes: 24 additions & 0 deletions spezi-invitation-code/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// This source file is part of the PAWS application based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

module.exports = {
root: true,
env: {
es2020: true,
node: true,
},
extends: [
"eslint:recommended",
"google",
],
rules: {
"quotes": ["error", "double"],
"max-len": ["error", {"code": 150}],
},
};

75 changes: 75 additions & 0 deletions spezi-invitation-code/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#
# This source file is part of the PAWS application based on the Stanford Spezi Template Application project
#
# SPDX-FileCopyrightText: 2023 Stanford University
#
# SPDX-License-Identifier: MIT
#


# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.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
72 changes: 72 additions & 0 deletions spezi-invitation-code/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// This source file is part of the StudyApplication based on the Stanford Spezi Template Application project
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

const admin = require("firebase-admin");
const {https} = require("firebase-functions/v2");
const {FieldValue} = require("firebase-admin/firestore");

class InvitationCodeVerifier {
constructor(firestore) {
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
this.firestore = firestore;
}

async verifyInvitationCode(invitationCode, userId) {
try {
const invitationCodeRef = this.firestore.doc(`invitationCodes/${invitationCode}`);
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
const invitationCodeDoc = await invitationCodeRef.get();

if (!invitationCodeDoc.exists || invitationCodeDoc.data().used) {
throw new https.HttpsError("not-found", "Invitation code not found or already used.");
}

const userStudyRef = this.firestore.doc(`users/${userId}`);
const userStudyDoc = await userStudyRef.get();

if (userStudyDoc.exists) {
throw new https.HttpsError("already-exists", "User is already enrolled in the study.");
}

await this.firestore.runTransaction(async (transaction) => {
transaction.set(userStudyRef, {
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
invitationCode: invitationCode,
dateOfEnrollment: FieldValue.serverTimestamp(),
});

transaction.update(invitationCodeRef, {
used: true,
usedBy: userId,
});
});
} catch (error) {
throw error;
}
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
}

async validateUserInvitationCode(userId) {
try {
const invitationQuerySnapshot = await this.firestore.collection("invitationCodes")
.where("usedBy", "==", userId)
.limit(1)
.get();

if (invitationQuerySnapshot.empty) {
throw new https.HttpsError("not-found", `No valid invitation code found for user ${userId}.`);
}

const userDoc = await this.firestore.doc(`users/${userId}`).get();

if (!userDoc.exists || userDoc.data().invitationCode !== invitationQuerySnapshot.docs[0].id) {
throw new https.HttpsError("failed-precondition", "User document does not exist or contains incorrect invitation code.");
}
} catch (error) {
throw error;
}
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
}
}

module.exports = InvitationCodeVerifier;
11 changes: 11 additions & 0 deletions spezi-invitation-code/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "spezi-invitation-code",
"version": "1.0.0",
"description": "Invitation code verifier for Spezi Firebase",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
MatthewTurk247 marked this conversation as resolved.
Show resolved Hide resolved
"author": "",
"license": "MIT"
}
3 changes: 3 additions & 0 deletions spezi-invitation-code/package.json.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2023 Stanford University

SPDX-License-Identifier: MIT
Loading