diff --git a/Makefile b/Makefile index 2467ccfa..9b4e59e3 100644 --- a/Makefile +++ b/Makefile @@ -124,11 +124,15 @@ build: launchpad-dev: @echo "--> Starting local Launchpad server using Firebase Hosting emulator..." + @echo " - Generating secure email hashes..." + @node scripts/generate-allowed-hashes.js @firebase serve --only hosting:launchpad --project=$(FIREBASE_ALIAS) # --- Deployment --- deploy-launchpad-hosting: @echo "--> Deploying Internal Launchpad to Firebase Hosting..." + @echo " - Generating secure email hashes..." + @node scripts/generate-allowed-hashes.js @echo " - Target: hosting:launchpad" @echo " - Project: $(FIREBASE_ALIAS)" @firebase deploy --only hosting:launchpad --project=$(FIREBASE_ALIAS) diff --git a/firebase.json b/firebase.json index b08c11a0..88dc5410 100644 --- a/firebase.json +++ b/firebase.json @@ -11,6 +11,7 @@ "public": "firebase/internal-launchpad", "ignore": [ "firebase.json", + "iap-users.txt", "**/.*", "**/node_modules/**" ] diff --git a/firebase/internal-launchpad/allowed-hashes.json b/firebase/internal-launchpad/allowed-hashes.json new file mode 100644 index 00000000..a3f1512d --- /dev/null +++ b/firebase/internal-launchpad/allowed-hashes.json @@ -0,0 +1,5 @@ +[ + "1b2e22bdec8f6493bf71ee535b6db6b4b5cd2d373f0ffb25524e229f3b5b7f5f", + "e075ff357ef35be2d55b0e383d59c5256980c492ada7ab84c84b2bb5ac26a73f", + "994b31c1aef3d59fe59bc3b8e1dec860a6fb3c73cbf41bdf45028e2c1ecbcf7a" +] \ No newline at end of file diff --git a/firebase/internal-launchpad/iap-users.txt b/firebase/internal-launchpad/iap-users.txt index c3133c2c..a9e897ef 100644 --- a/firebase/internal-launchpad/iap-users.txt +++ b/firebase/internal-launchpad/iap-users.txt @@ -5,4 +5,10 @@ # Both internal (@krowwithus.com) and external emails are supported. user:admin@krowwithus.com + +# External users - Oloodi employees user:boris@oloodi.com +user:achintha.isuru@oloodi.com + +# External users - Legendary employees + diff --git a/firebase/internal-launchpad/index.html b/firebase/internal-launchpad/index.html index 463cf70a..472f97d7 100644 --- a/firebase/internal-launchpad/index.html +++ b/firebase/internal-launchpad/index.html @@ -398,19 +398,20 @@ async function checkAccess(email) { try { - // Fetch the whitelist - const res = await fetch('iap-users.txt'); + // 1. Fetch the secure list of hashes + const res = await fetch('allowed-hashes.json'); if (!res.ok) return false; - const text = await res.text(); + const allowedHashes = await res.json(); - // Parse lines - const lines = text.split('\n'); - const allowedEmails = lines - .map(line => line.trim()) - .filter(line => line && !line.startsWith('#')) - .map(line => line.replace(/^user:/, '').trim()); - - return allowedEmails.includes(email); + // 2. Hash the user's email (SHA-256) + const normalizedEmail = email.trim().toLowerCase(); + const msgBuffer = new TextEncoder().encode(normalizedEmail); + const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + + // 3. Compare + return allowedHashes.includes(hashHex); } catch (e) { console.error("Failed to check access list:", e); return false; diff --git a/mobile-apps/apps/krow_client/.keep b/mobile-apps/apps/krow_client/.keep new file mode 100644 index 00000000..e69de29b diff --git a/scripts/generate-allowed-hashes.js b/scripts/generate-allowed-hashes.js new file mode 100644 index 00000000..57a09784 --- /dev/null +++ b/scripts/generate-allowed-hashes.js @@ -0,0 +1,31 @@ +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const INPUT_FILE = path.join(__dirname, '../firebase/internal-launchpad/iap-users.txt'); +const OUTPUT_FILE = path.join(__dirname, '../firebase/internal-launchpad/allowed-hashes.json'); + +try { + const data = fs.readFileSync(INPUT_FILE, 'utf8'); + const lines = data.split('\n'); + + const hashes = lines + .map(line => line.trim()) + .filter(line => line && !line.startsWith('#')) // Ignore empty lines and comments + .map(line => line.replace(/^user:/, '').trim().toLowerCase()) // Clean email + .map(email => { + // Create SHA-256 hash + return crypto.createHash('sha256').update(email).digest('hex'); + }); + + const jsonContent = JSON.stringify(hashes, null, 2); + fs.writeFileSync(OUTPUT_FILE, jsonContent); + + console.log(`✅ Successfully generated ${hashes.length} secure hashes from iap-users.txt`); + console.log(` Output: ${OUTPUT_FILE}`); + +} catch (err) { + console.error('❌ Error generating hashes:', err); + process.exit(1); +} +