diff --git a/.firebaserc b/.firebaserc index 9862bb42..f0bbe5f5 100644 --- a/.firebaserc +++ b/.firebaserc @@ -1,6 +1,6 @@ { "projects": { - "default": "parallel-cf800", + "default": "parallel-beta-31dc4", "prod": "parallel-cf800", "beta": "parallel-beta-31dc4" } diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml new file mode 100644 index 00000000..db0c31f2 --- /dev/null +++ b/.github/workflows/beta.yml @@ -0,0 +1,40 @@ +name: Deploy Beta + +on: + workflow_dispatch: + pull_request: + types: [edited] + +jobs: + deploy-beta: + name: Deploy + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Node.js version from .nvmrc + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + + - name: Write service account + run: | + mkdir private + echo "$BETA_FIREBASE_SERVICE_ACCOUNT" > ./private/service-account.json + echo '${{ secrets.BETA_FIREBASE_SERVICE_ACCOUNT }}' > gcloud.json + env: + BETA_FIREBASE_SERVICE_ACCOUNT: ${{ secrets.BETA_FIREBASE_SERVICE_ACCOUNT }} + shell: bash + + - name: Install + run: | + npm install + shell: bash + + - name: Deploy + env: + GOOGLE_APPLICATION_CREDENTIALS: gcloud.json + run: | + npm run deploy + shell: bash diff --git a/functions/index.js b/functions/index.js index d14d420c..289477cd 100644 --- a/functions/index.js +++ b/functions/index.js @@ -4,9 +4,10 @@ const firebase = require('firebase-admin'); +const serviceAccount = require('./build/service-account.json'); firebase.initializeApp({ - credential: firebase.credential.cert(require('./build/service-account.json')), - databaseURL: `https://parallel-cf800.firebaseio.com`, + credential: firebase.credential.cert(serviceAccount), + databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`, }); const fs = require('fs'); @@ -87,6 +88,16 @@ function letterOrder(a, b) { return a < b ? -1 : a > b ? 1 : 0; } +const firebaseClientConfig = serviceAccount.project_id === 'parallel-cf800' ? { + apiKey: "AIzaSyCrQ_PdH-05lcNWETGvGfiwO3MBXk_WeVU", + projectId: "parallel-cf800", + authDomain: "parallel-cf800.firebaseapp.com", +} : { + apiKey: "AIzaSyDk4_ME-Uy1D3Yjg94Af7Gzhg3I1xNYWp8", + projectId: "parallel-beta-31dc4", + authDomain: "parallel-beta-31dc4.firebaseapp.com", +}; + // ----------------------------------------------------------------------------- // Set up Express App @@ -107,6 +118,8 @@ app.use((req, res, next) => { res.locals.levelNamesWithAges = LEVEL_NAMES_WITH_AGES; res.locals.path = req.path.replace(/\/$/, ''); res.locals.scoreClass = scoreClass; + res.locals.firebaseClientConfig = firebaseClientConfig; + res.locals.isBeta = serviceAccount.project_id.includes('beta'); if (req.user && req.user.showWelcomeMsg && !req.query.latest && !req.path.includes('/api')) { userDB.doc(req.user.uid) // async diff --git a/functions/views/_layout.pug b/functions/views/_layout.pug index 76fe4d8f..3d8d330f 100644 --- a/functions/views/_layout.pug +++ b/functions/views/_layout.pug @@ -34,8 +34,15 @@ html if user script!= 'window.USER_ID = "' + user.uid + '";' + script!= 'window.FIREBASE_CONFIG = ' + JSON.stringify(firebaseClientConfig) + ';' + body #vue + if isBeta + .beta + div You are on our Beta Testing Site! + div The information & events on this page are for testing purposes and should not be followed. + a(href="https://parallel.org.uk") Click here to return to the production site. .headerWrapper .header if !sidebarDisabled diff --git a/package.json b/package.json index af6c06ae..d45db286 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,10 @@ }, "scripts": { "start": "grunt build && npm run serve", - "serve": "grunt concurrent & GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase serve --project prod", - "export-users": "cross-env GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase auth:export ./private/tmp-users.json --format=json --project prod", - "deploy": "grunt && GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase deploy --project prod", + "serve:old": "grunt concurrent & GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase serve --project beta", + "serve": "grunt concurrent & GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase serve --project $(node scripts/get-project-alias.js)", + "export-users": "cross-env GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase auth:export ./private/tmp-users.json --format=json --project $(node scripts/get-project-alias.js)", + "deploy": "grunt && GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase deploy --project $(node scripts/get-project-alias.js)", "convert-teachers": "node scripts/convert-teachers.js", "convert-students": "node scripts/convert-students.js", "get-users": "node scripts/get-users.js", @@ -20,7 +21,7 @@ "get-tts-results": "node scripts/get-tts-results.js", "update-results": "node scripts/update-results.js", "set-points": "node scripts/set-points.js", - "start-marsh": "grunt build && concurrently \"grunt concurrent\" \"GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase serve --project prod\"" + "start-marsh": "grunt build && concurrently \"grunt concurrent\" \"GOOGLE_APPLICATION_CREDENTIALS=private/service-account.json firebase serve --project $(node scripts/get-project-alias.js)\"" }, "devDependencies": { "@babel/core": "^7.15.0", diff --git a/scripts/change-email.js b/scripts/change-email.js index 5e96e619..0ff833fb 100644 --- a/scripts/change-email.js +++ b/scripts/change-email.js @@ -8,7 +8,7 @@ const to = 'lalanthi026@googlemail.com' fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: "https://parallel-cf800.firebaseio.com", + databaseURL: require('./utils/firebase-config').databaseURL, }); const run = () => diff --git a/scripts/convert-students.js b/scripts/convert-students.js index d55c3a4e..6fa938c5 100644 --- a/scripts/convert-students.js +++ b/scripts/convert-students.js @@ -9,7 +9,7 @@ const STUDENTS = [ fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const file = path.join(__dirname, `../private/tmp-users.json`); diff --git a/scripts/convert-teachers.js b/scripts/convert-teachers.js index c537ad5f..331da403 100644 --- a/scripts/convert-teachers.js +++ b/scripts/convert-teachers.js @@ -10,7 +10,7 @@ const TEACHERS = [ fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const file = path.join(__dirname, `../private/tmp-users.json`); diff --git a/scripts/delete-accounts.js b/scripts/delete-accounts.js index 2b6bafbb..60d3cb2e 100644 --- a/scripts/delete-accounts.js +++ b/scripts/delete-accounts.js @@ -7,7 +7,7 @@ const USERS = [ fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); async function deleteAccount(email) { diff --git a/scripts/get-project-alias.js b/scripts/get-project-alias.js new file mode 100644 index 00000000..b2cea886 --- /dev/null +++ b/scripts/get-project-alias.js @@ -0,0 +1,2 @@ +const { projectAlias } = require('./utils/firebase-config'); +process.stdout.write(projectAlias); diff --git a/scripts/privacy-approve.js b/scripts/privacy-approve.js index bf8b8e65..18f36a3f 100644 --- a/scripts/privacy-approve.js +++ b/scripts/privacy-approve.js @@ -20,7 +20,7 @@ const dryRun = true; // when true, will just log what it will write, but not sav fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/scripts/privacy-y8webinar.js b/scripts/privacy-y8webinar.js index 9b6ab57f..ecf54ac2 100644 --- a/scripts/privacy-y8webinar.js +++ b/scripts/privacy-y8webinar.js @@ -20,7 +20,7 @@ const dryRun = true; // when true, will just log what it will write, but not sav fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/scripts/recover-account.js b/scripts/recover-account.js index ae034b92..b2227ddd 100644 --- a/scripts/recover-account.js +++ b/scripts/recover-account.js @@ -27,7 +27,7 @@ const makePassword = () => { fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: "https://parallel-cf800.firebaseio.com", + databaseURL: require('./utils/firebase-config').databaseURL, }); const updateUserPassword = (email) => diff --git a/scripts/set-account-level.js b/scripts/set-account-level.js index 0a9d4c47..11ccd324 100644 --- a/scripts/set-account-level.js +++ b/scripts/set-account-level.js @@ -12,7 +12,7 @@ const isEuclidAdmin = true; fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: "https://parallel-cf800.firebaseio.com", + databaseURL: require('./utils/firebase-config').databaseURL, }); const setAdmin = () => { diff --git a/scripts/switch-data.js b/scripts/switch-data.js index e4e5fd0c..b7391c2a 100644 --- a/scripts/switch-data.js +++ b/scripts/switch-data.js @@ -10,7 +10,7 @@ const TO_EMAIL = "jmanyoma20@gmail.com"; fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: "https://parallel-cf800.firebaseio.com", + databaseURL: require('./utils/firebase-config').databaseURL, }); const getAnswerCount = (data) => diff --git a/scripts/temp-update-levels/fix-levels-run.js b/scripts/temp-update-levels/fix-levels-run.js index 135b617e..eed6c023 100644 --- a/scripts/temp-update-levels/fix-levels-run.js +++ b/scripts/temp-update-levels/fix-levels-run.js @@ -8,7 +8,7 @@ const limit = promiseLimit(400); fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('../utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/scripts/update-euclid-data.js b/scripts/update-euclid-data.js index d724d5a5..19c1f2cf 100644 --- a/scripts/update-euclid-data.js +++ b/scripts/update-euclid-data.js @@ -16,7 +16,7 @@ const dryRun = true; // when true, will just log what it will write, but not sav fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/scripts/update-results.js b/scripts/update-results.js index d4b77d42..949ed9f8 100644 --- a/scripts/update-results.js +++ b/scripts/update-results.js @@ -13,7 +13,7 @@ const ADD_POINTS = 2; fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/scripts/utils/downloadUsers.js b/scripts/utils/downloadUsers.js index 608e821c..067ce1ad 100644 --- a/scripts/utils/downloadUsers.js +++ b/scripts/utils/downloadUsers.js @@ -7,7 +7,7 @@ const serviceAccount = require('../../private/service-account.json'); fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('./firebase-config').databaseURL }); const cacheFilePath = path.join(__dirname, `../../private/cache-users.json`); diff --git a/scripts/utils/firebase-config.js b/scripts/utils/firebase-config.js new file mode 100644 index 00000000..4b43d476 --- /dev/null +++ b/scripts/utils/firebase-config.js @@ -0,0 +1,15 @@ +const path = require('path'); +const serviceAccount = require(path.join(__dirname, '../../private/service-account.json')); + +const PROJECT_ALIASES = { + 'parallel-beta-31dc4': 'beta', + 'parallel-cf800': 'prod', +}; + +const projectId = serviceAccount.project_id; +const databaseURL = `https://${projectId}.firebaseio.com`; +const projectAlias = PROJECT_ALIASES[projectId] || projectId; + +console.error('\n\n\n\n\nRunning with Firebase project:', projectId, '(', projectAlias, ')\n\n\n'); + +module.exports = { projectId, databaseURL, projectAlias }; diff --git a/scripts/yearly-updates/delete-old-users.js b/scripts/yearly-updates/delete-old-users.js index 3e795d14..80e2a904 100644 --- a/scripts/yearly-updates/delete-old-users.js +++ b/scripts/yearly-updates/delete-old-users.js @@ -5,7 +5,7 @@ const serviceAccount = require("../../private/service-account.json"); fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: "https://parallel-cf800.firebaseio.com", + databaseURL: require('../utils/firebase-config').databaseURL, }); const keysToRemove = [ diff --git a/scripts/yearly-updates/update-users-upload.js b/scripts/yearly-updates/update-users-upload.js index 6210dfea..b5235c6b 100644 --- a/scripts/yearly-updates/update-users-upload.js +++ b/scripts/yearly-updates/update-users-upload.js @@ -8,7 +8,7 @@ const limit = promiseLimit(400); fb.initializeApp({ credential: fb.credential.cert(serviceAccount), - databaseURL: 'https://parallel-cf800.firebaseio.com' + databaseURL: require('../utils/firebase-config').databaseURL }); const userDb = fb.firestore().collection('users'); diff --git a/static/scripts/main.js b/static/scripts/main.js index 8dd1856a..9533bbdb 100755 --- a/static/scripts/main.js +++ b/static/scripts/main.js @@ -111,11 +111,7 @@ document.addEventListener("wheel", function(event){ }); document.addEventListener('DOMContentLoaded', function() { - firebase.initializeApp({ - apiKey: "AIzaSyCrQ_PdH-05lcNWETGvGfiwO3MBXk_WeVU", - projectId: "parallel-cf800", - authDomain: "parallel-cf800.firebaseapp.com", - }); + firebase.initializeApp(window.FIREBASE_CONFIG); const user = getUser(); const challenge = window.PARALLELOGRAM ? getChallenge() : null; diff --git a/static/styles/layout.less b/static/styles/layout.less index c9b84f26..96759e61 100644 --- a/static/styles/layout.less +++ b/static/styles/layout.less @@ -23,6 +23,17 @@ html { line-height: 1.8; } +.beta { + background-color: orange; + margin: 0px -1rem; + text-align: center; + + a { + color: blue; + text-decoration: underline; + } +} + #logo { background: url('/images/logo.png'); background-size: cover;