Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 1x 1x 1x 1x 1x 46x 8x 8x 38x 22x 22x 88x 22x 1x 41x 41x 34x 34x 29x 27x 19x 32x 13x 13x 4x 5x 5x 4x 4x 3x 3x 32x 10x 22x 2x 2x 1x 5x 4x 1x | /**
* Roadmap page authentication routes.
*
* GET /roadmap/me → check if ShyTalk account exists for authenticated user
* POST /roadmap/signout → sign out acknowledgment
*/
const router = require('express').Router();
const { db } = require('../utils/firebase');
const log = require('../utils/log');
// Fields safe to expose on the roadmap profile
const SAFE_FIELDS = ['uniqueId', 'displayName', 'avatarUrl', 'profilePhotoUrl'];
const DOWNLOAD_LINKS = {
android: 'https://play.google.com/store/apps/details?id=com.shyden.shytalk',
ios: 'https://apps.apple.com/app/shytalk/id6741488545',
};
function requireAuth(req, res) {
if (!req.auth || (!req.auth.uniqueId && !req.auth.uid)) {
res.status(401).json({ error: 'Authentication required' });
return true;
}
return false;
}
function pickSafeFields(data) {
const safe = {};
for (const key of SAFE_FIELDS) {
Eif (key in data) safe[key] = data[key];
}
return safe;
}
// ─── GET /roadmap/me ────────────────────────────────────────────
router.get('/roadmap/me', async (req, res) => {
try {
if (requireAuth(req, res)) return;
let userData = null;
// Try direct lookup by uniqueId
if (req.auth.uniqueId) {
const userDoc = await db.doc(`users/${req.auth.uniqueId}`).get();
if (userDoc.exists) {
userData = { uniqueId: Number(req.auth.uniqueId), ...userDoc.data() };
}
}
// Fallback: lookup via identityMap using Firebase UID
if (!userData && req.auth.uid) {
const idSnap = await db
.collection('identityMap')
.where('firebaseUid', '==', req.auth.uid)
.get();
if (!idSnap.empty) {
for (const idDoc of idSnap.docs) {
const idData = idDoc.data();
// Skip unlinked entries
if (idData.unlinked) continue;
const userDoc = await db.doc(`users/${idData.uniqueId}`).get();
if (userDoc.exists) {
userData = { uniqueId: idData.uniqueId, ...userDoc.data() };
break;
}
}
}
}
// No ShyTalk account found
if (!userData) {
return res.status(404).json({
error:
'No ShyTalk account found. Download the app to create an account, then come back to login.',
downloadLinks: DOWNLOAD_LINKS,
});
}
// Return safe profile fields only
res.json(pickSafeFields(userData));
} catch (err) {
log.error('roadmap-auth', 'Failed to check account', {
error: err.message,
});
res.status(500).json({ error: 'Internal server error' });
}
});
// ─── POST /roadmap/signout ──────────────────────────────────────
router.post('/roadmap/signout', (req, res) => {
if (requireAuth(req, res)) return;
// Sign out is handled client-side (Firebase Auth).
// This endpoint acknowledges the sign out.
res.json({ success: true });
});
module.exports = router;
|