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

Refactor backend #26

Merged
merged 36 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
af830b4
refactor types and utils into a shared "utils" package
TiboX2021 May 3, 2024
fffb8f3
remove allowedStageProgressionMap in favor of predefined progression …
TiboX2021 May 1, 2024
d610704
refactor seeder in order to reflect latest firestore schema
TiboX2021 May 3, 2024
9c163e5
update webapp firebase config to make cloud functions url depend on f…
TiboX2021 May 3, 2024
8b75ac6
base implementations for repositories (and experiment repository)
TiboX2021 May 6, 2024
efe49a9
update types to better match the new firestore structure
TiboX2021 May 6, 2024
94ca90f
implement basic version of participant repository (readonly profile a…
TiboX2021 May 6, 2024
1f0e08f
create base for chat repository and refactor chat
TiboX2021 May 6, 2024
b69d294
more some of the vscode config
TiboX2021 May 7, 2024
9e93bda
initialize public data and and publish chat state through triggers
TiboX2021 May 7, 2024
e0edfb6
update firestore read/write rules (TODO validation)
TiboX2021 May 7, 2024
437940a
create experimenter repository (use it as a singleton)
TiboX2021 May 7, 2024
6ec4915
create and inject global app state
TiboX2021 May 7, 2024
14a5c4e
more beautiful app state service
TiboX2021 May 7, 2024
583557f
implement helper participant service to wrap appstate calls
TiboX2021 May 8, 2024
76e2273
some fixes and cleanup
TiboX2021 May 8, 2024
2729129
agregate stage data in participant service
TiboX2021 May 8, 2024
3b9ba19
remove old services (replaced with global appstate and repositories)
TiboX2021 May 8, 2024
748dcf4
refactor experimenter webapp pages for read operations
TiboX2021 May 8, 2024
1ae539a
fully working readonly version of the app (finished frontend data rew…
TiboX2021 May 14, 2024
e1b1ddd
refactor the cloud functions & mutations (in progress)
TiboX2021 May 15, 2024
3ed803f
move validation to utils with peer dependency
TiboX2021 May 16, 2024
522cc90
refactor webapp callable declarations
TiboX2021 May 16, 2024
cbecd7f
remove tanstack
TiboX2021 May 16, 2024
af19afa
fix frontend build
TiboX2021 May 16, 2024
cd3e78d
move mutation functions to repositories
TiboX2021 May 16, 2024
0025465
integrate mutations within the frontend (wip)
TiboX2021 May 16, 2024
dd95a08
use async
TiboX2021 May 16, 2024
e1dded0
use tsup to build the shaed utils package in order to avoid esm/cjs pain
TiboX2021 May 17, 2024
a2d87d4
some fixes to make the app work completely
TiboX2021 May 21, 2024
613b86e
replaced boilerplate items with actual items form the list
LeoLaugier May 17, 2024
4d07c02
seeding the database with 5 random pairs out of all possible pairs (n…
LeoLaugier May 17, 2024
51fd14c
cleanup seeder script
TiboX2021 May 21, 2024
d641929
improve chat ui messages
TiboX2021 May 21, 2024
68c53c4
Merge pull request #29 from PAIR-code/all-items
TiboX2021 May 21, 2024
f97092b
fix chat timer
TiboX2021 May 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .firebaserc.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"projects": {
"default": "your-project-id-here"
"default": "your-project-id"
}
}
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"recommendations": [
"ethansk.restore-terminals" // Restore Terminals extension
"ethansk.restore-terminals", // Restore Terminals extension
"angular.ng-template"
]
}
13 changes: 12 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,16 @@
}
]
}
]
],
"editor.tabSize": 2,
"[html][typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
},
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ This is a repository to support collaboration on using LLMs in behavioral econom

## Shared Utilities

The webapp, cloud functions, and seeding scripts share some utilities. These are located in the [`utils`](./utils) directory.

To build the shared utilities and watch for changes, run the following command:

```bash
cd utils
npm run build:watch
```

The shared utilities are built using [`tsup`](https://tsup.egoist.dev) to produce both esm (for the webapp) and cjs (for the cloud functions and scripts) code.

## Firebase

This project uses Firebase as its backend. The configuration can be found in the [`.firebaserc`](./.firebaserc) and [`firebase.json`](./firebase.json) files.
Expand All @@ -75,6 +75,7 @@ Create the configuration files for a default firebase project:
```bash
cp .firebaserc.example .firebaserc
cp webapp/src/lib/api/firebase-config.example.ts webapp/src/lib/api/firebase-config.ts
cp scripts/service-account.example.json scripts/service-account.json
```

This should be enough for local development with emulators. Before deploying to production, be sure to:
Expand Down
1 change: 0 additions & 1 deletion emulator_test_config/auth_export/accounts.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"email": "experimenter@google.com"
}
],
"photoUrl": "",
"customAttributes": "{\"role\": \"experimenter\"}"
},
{
Expand Down
94 changes: 80 additions & 14 deletions firestore/firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,92 @@ rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {

// Rules for the messages collection
match /messages/{messageId} {
allow list: if request.auth.token.role == 'experimenter' || request.auth.token.role == 'participant';
// ***************************************************************************************** //
// VALIDATION FUNCTIONS //
// ***************************************************************************************** //

function validateString(value) {
return value is string;
}

function validateInt(value) {
return value is int
}

function validateFloat(value) {
return value is int || value is float;
}

// Rules for the participants_progressions collection
match /participants_progressions/{progressionId} {
// Allow single-document reads
allow read: if true;
function validateTimestamp(value) {
return value.keys().hasAll(['seconds', 'nanoseconds']) &&
validateNumber(value.seconds) &&
validateNumber(value.nanoseconds);
}

// Rules for the chat toggle collection
match /participants_ready_to_end_chat/{chatId} {
// Allow single document reads
allow read: if true;
// Validate the profile
function validateProfile(value) {
return value.keys().hasOnly(['pronouns', 'avatarUrl', 'name', 'acceptTosTimestamp']) &&
(!('pronouns' in value) || validateString(value.pronouns)) &&
(!('avatarUrl' in value) || validateString(value.avatarUrl)) &&
(!('name' in value) || validateString(value.name)) &&
(!('acceptTosTimestamp' in value) || validateTimestamp(value.acceptTosTimestamp));
}

// Else: disallow everything (access via cloud functions only)
match /{document=**} {
allow read, write: if false;
// Validate the chat document data
function validateChat(value) {
return value.keys().hasOnly(['readyToEndChat']) && value.readyToEndChat == false;
}

// ***************************************************************************************** //
// RULES //
// ***************************************************************************************** //

// Template rules (experimenter-only)
match /templates/{documents=**} {
allow read: if request.auth.token.role == 'experimenter';
allow write: if false; // Complex validation through cloud functions
}

// Experiment rules
match /experiments/{experimentId} {

allow get: if true;
allow list: if request.auth.token.role == 'experimenter';
allow delete: if request.auth.token.role == 'experimenter';
allow write: if false; // Complex validation through cloud functions

match /stages/{stageId} {
allow read: if true; // Public read
allow write: if false; // Write as experimenter through cloud functions
}

match /publicStageData/{stageId} {
allow read: if true;
allow write: if false; // Public readonly for everyone. Computed through firestore triggers
}

// Participant rules
match /participants/{participantId} {

allow get: if true; // Public if you know the ID
allow list: if request.auth.token.role == 'experimenter'; // Avoid leaking IDs (only experimenters can view them)
allow update: if true; // validateProfile(request.resource.data); // emulator bug

match /stages/{stageId} {
allow read: if true;
allow write: if false; // Complex validation through cloud functions
}

match /chats/{chatId} {
allow read: if true;
allow update: if true; // validateChat(request.resource.data); // emulator bug

match /messages/{messageId} {
allow read: if true;
allow write: if false; // Replication to all participants done through cloud functions in order to avoid trigger loops
}
}
}
}
}
}