Manifold for Teams: Support different Firestore dbs (#53)

* Add Firebase config for TheoremOne

* Fix build

* Check in Firebase indexes

* Whitelist admins and new users by email
This commit is contained in:
Austin Chen 2022-02-26 22:08:50 -08:00 committed by GitHub
parent 77b4ca4f22
commit ebed7c15c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 294 additions and 29 deletions

14
common/access.ts Normal file
View File

@ -0,0 +1,14 @@
export function isWhitelisted(email?: string) {
return true
// e.g. return email.endsWith('@theoremone.co') || isAdmin(email)
}
export function isAdmin(email: string) {
const ADMINS = [
'akrolsmir@gmail.com', // Austin
'jahooma@gmail.com', // James
'taowell@gmail.com', // Stephen
'manticmarkets@gmail.com', // Manifold
]
return ADMINS.includes(email)
}

View File

@ -5,6 +5,7 @@
"source": "functions" "source": "functions"
}, },
"firestore": { "firestore": {
"rules": "firestore.rules" "rules": "firestore.rules",
"indexes": "firestore.indexes.json"
} }
} }

234
firestore.indexes.json Normal file
View File

@ -0,0 +1,234 @@
{
"indexes": [
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "creatorId",
"order": "ASCENDING"
},
{
"fieldPath": "createdTime",
"order": "DESCENDING"
}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "isResolved",
"order": "ASCENDING"
},
{
"fieldPath": "closeTime",
"order": "ASCENDING"
}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "isResolved",
"order": "ASCENDING"
},
{
"fieldPath": "visibility",
"order": "ASCENDING"
},
{
"fieldPath": "closeTime",
"order": "ASCENDING"
}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "isResolved",
"order": "ASCENDING"
},
{
"fieldPath": "visibility",
"order": "ASCENDING"
},
{
"fieldPath": "volume24Hours",
"order": "DESCENDING"
}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "isResolved",
"order": "ASCENDING"
},
{
"fieldPath": "volume24Hours",
"order": "DESCENDING"
}
]
},
{
"collectionGroup": "contracts",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "slug",
"order": "ASCENDING"
},
{
"fieldPath": "createdTime",
"order": "DESCENDING"
}
]
}
],
"fieldOverrides": [
{
"collectionGroup": "answers",
"fieldPath": "username",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "bets",
"fieldPath": "createdTime",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "bets",
"fieldPath": "userId",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "comments",
"fieldPath": "createdTime",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "comments",
"fieldPath": "userUsername",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
},
{
"collectionGroup": "followers",
"fieldPath": "userId",
"indexes": [
{
"order": "ASCENDING",
"queryScope": "COLLECTION"
},
{
"order": "DESCENDING",
"queryScope": "COLLECTION"
},
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
},
{
"order": "ASCENDING",
"queryScope": "COLLECTION_GROUP"
}
]
}
]
}

View File

@ -1,3 +1,6 @@
# Secrets
.env*
# Compiled JavaScript files # Compiled JavaScript files
lib/**/*.js lib/**/*.js
lib/**/*.js.map lib/**/*.js.map

View File

@ -14,6 +14,7 @@ import {
cleanUsername, cleanUsername,
} from '../../common/util/clean-username' } from '../../common/util/clean-username'
import { sendWelcomeEmail } from './emails' import { sendWelcomeEmail } from './emails'
import { isWhitelisted } from '../../common/access'
export const createUser = functions export const createUser = functions
.runWith({ minInstances: 1 }) .runWith({ minInstances: 1 })
@ -32,6 +33,9 @@ export const createUser = functions
const fbUser = await admin.auth().getUser(userId) const fbUser = await admin.auth().getUser(userId)
const email = fbUser.email const email = fbUser.email
if (!isWhitelisted(email)) {
return { status: 'error', message: `${email} is not whitelisted` }
}
const emailName = email?.replace(/@.*$/, '') const emailName = email?.replace(/@.*$/, '')
const rawName = fbUser.displayName || emailName || 'User' + randomString(4) const rawName = fbUser.displayName || emailName || 'User' + randomString(4)

View File

@ -1,12 +1,8 @@
import { useUser } from './use-user' import { isAdmin } from '../../common/access'
import { usePrivateUser, useUser } from './use-user'
export const useAdmin = () => { export const useAdmin = () => {
const user = useUser() const user = useUser()
const adminIds = [ const privateUser = usePrivateUser(user?.id)
'igi2zGXsfxYPgB0DJTXVJVmwCOr2', // Austin return isAdmin(privateUser?.email || '')
'5LZ4LgYuySdL1huCWe7bti02ghx2', // James
'tlmGNz9kjXc2EteizMORes4qvWl2', // Stephen
'IPTOzEqrpkWmEzh6hwvAyY9PqFb2', // Manifold
]
return adminIds.includes(user?.id || '')
} }

View File

@ -1,10 +1,11 @@
import { getFirestore } from '@firebase/firestore' import { getFirestore } from '@firebase/firestore'
import { initializeApp, getApps, getApp } from 'firebase/app' import { initializeApp, getApps, getApp } from 'firebase/app'
// Used to decide which Stripe instance to point to
export const isProd = process.env.NEXT_PUBLIC_FIREBASE_ENV !== 'DEV' export const isProd = process.env.NEXT_PUBLIC_FIREBASE_ENV !== 'DEV'
const firebaseConfig = isProd const FIREBASE_CONFIGS = {
? { DEV: {
apiKey: 'AIzaSyDp3J57vLeAZCzxLD-vcPaGIkAmBoGOSYw', apiKey: 'AIzaSyDp3J57vLeAZCzxLD-vcPaGIkAmBoGOSYw',
authDomain: 'mantic-markets.firebaseapp.com', authDomain: 'mantic-markets.firebaseapp.com',
projectId: 'mantic-markets', projectId: 'mantic-markets',
@ -12,8 +13,8 @@ const firebaseConfig = isProd
messagingSenderId: '128925704902', messagingSenderId: '128925704902',
appId: '1:128925704902:web:f61f86944d8ffa2a642dc7', appId: '1:128925704902:web:f61f86944d8ffa2a642dc7',
measurementId: 'G-SSFK1Q138D', measurementId: 'G-SSFK1Q138D',
} },
: { PROD: {
apiKey: 'AIzaSyBoq3rzUa8Ekyo3ZaTnlycQYPRCA26VpOw', apiKey: 'AIzaSyBoq3rzUa8Ekyo3ZaTnlycQYPRCA26VpOw',
authDomain: 'dev-mantic-markets.firebaseapp.com', authDomain: 'dev-mantic-markets.firebaseapp.com',
projectId: 'dev-mantic-markets', projectId: 'dev-mantic-markets',
@ -21,8 +22,20 @@ const firebaseConfig = isProd
messagingSenderId: '134303100058', messagingSenderId: '134303100058',
appId: '1:134303100058:web:27f9ea8b83347251f80323', appId: '1:134303100058:web:27f9ea8b83347251f80323',
measurementId: 'G-YJC9E37P37', measurementId: 'G-YJC9E37P37',
},
THEOREMONE: {
apiKey: 'AIzaSyBSXL6Ys7InNHnCKSy-_E_luhh4Fkj4Z6M',
authDomain: 'theoremone-manifold.firebaseapp.com',
projectId: 'theoremone-manifold',
storageBucket: 'theoremone-manifold.appspot.com',
messagingSenderId: '698012149198',
appId: '1:698012149198:web:b342af75662831aa84b79f',
measurementId: 'G-Y3EZ1WNT6E',
},
} }
const ENV = process.env.NEXT_PUBLIC_FIREBASE_ENV ?? 'PROD'
// @ts-ignore
const firebaseConfig = FIREBASE_CONFIGS[ENV]
// Initialize Firebase // Initialize Firebase
export const app = getApps().length ? getApp() : initializeApp(firebaseConfig) export const app = getApps().length ? getApp() : initializeApp(firebaseConfig)