diff --git a/app/api/projects/route.ts b/app/api/projects/route.ts index 6c82c7b..bd6018e 100644 --- a/app/api/projects/route.ts +++ b/app/api/projects/route.ts @@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'; import { db } from '../../../lib/db'; import { projects, teamMembers, projectOptions, categories, categoryOptionValues,users } from '../../../lib/schema'; import { eq, and, sql } from 'drizzle-orm'; -import { getAuth } from 'firebase-admin/auth'; +import { adminAuth } from '../../../lib/firebase/firebaseadmin'; import { cookies } from 'next/headers'; @@ -77,7 +77,7 @@ export async function POST(req: NextRequest) { return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); } - const decodedToken = await getAuth().verifyIdToken(token); + const decodedToken = await adminAuth.verifyIdToken(token); console.log('Decoded Firebase UID:', decodedToken.uid); const firebaseUid = decodedToken.uid; diff --git a/check-db.js b/check-db.js new file mode 100644 index 0000000..fb354e9 --- /dev/null +++ b/check-db.js @@ -0,0 +1,49 @@ +const { Pool } = require('pg'); +require('dotenv').config({ path: '.env' }); + +async function checkDatabase() { + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: { rejectUnauthorized: false } + }); + + try { + console.log('šŸ”Œ Connecting to database...'); + + // Test connection + const client = await pool.connect(); + console.log('āœ… Database connection successful!'); + + // Get all tables + const tablesResult = await client.query(` + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + ORDER BY table_name; + `); + + console.log('\nšŸ“‹ Current tables in database:'); + tablesResult.rows.forEach(row => { + console.log(` - ${row.table_name}`); + }); + + // Get table counts + console.log('\nšŸ“Š Table record counts:'); + for (const table of tablesResult.rows) { + try { + const countResult = await client.query(`SELECT COUNT(*) FROM "${table.table_name}"`); + console.log(` ${table.table_name}: ${countResult.rows[0].count} records`); + } catch (err) { + console.log(` ${table.table_name}: Error getting count - ${err.message}`); + } + } + + client.release(); + } catch (err) { + console.error('āŒ Database connection failed:', err.message); + } finally { + await pool.end(); + } +} + +checkDatabase(); \ No newline at end of file diff --git a/drizzle.config.ts b/drizzle.config.ts index 9e41626..decea7b 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -2,8 +2,8 @@ import type { Config } from "drizzle-kit"; import * as dotenv from "dotenv"; import { resolve } from "path"; -// šŸ”„ Explicitly load .env.local -dotenv.config({ path: resolve(__dirname, ".env.local") }); +// šŸ”„ Explicitly load .env +dotenv.config({ path: resolve(__dirname, ".env") }); export default { schema: "./lib/schema.ts", // adjust if you use a different path diff --git a/lib/db.ts b/lib/db.ts index 82213fb..7f23509 100644 --- a/lib/db.ts +++ b/lib/db.ts @@ -1,5 +1,5 @@ import * as dotenv from "dotenv"; -dotenv.config({ path: ".env.local" }); +dotenv.config({ path: ".env" }); import { drizzle } from "drizzle-orm/node-postgres"; import { Pool } from "pg"; diff --git a/lib/firebase/auth.ts b/lib/firebase/auth.ts index e0b841c..b767921 100644 --- a/lib/firebase/auth.ts +++ b/lib/firebase/auth.ts @@ -1,6 +1,6 @@ // Import User and other necessary types/functions from Firebase Auth import { signInWithPopup, GoogleAuthProvider, User, UserCredential , getAuth } from 'firebase/auth'; -import { doc, getDoc } from 'firebase/firestore'; +import { doc, getDoc, enableNetwork, disableNetwork } from 'firebase/firestore'; import { auth, firestore } from './config'; // Ensure you are correctly importing from your Firebase config // Function to track authentication state changes @@ -13,8 +13,10 @@ export async function signInWithGoogle(): Promise<{ user:User; isAdmin: boolean const provider = new GoogleAuthProvider(); provider.setCustomParameters({ display: "popup" }); // Force popup - try { + // Ensure network is enabled before attempting sign-in + await enableNetwork(firestore); + const result: UserCredential = await signInWithPopup(auth, provider); const user: User = result.user; @@ -24,29 +26,31 @@ export async function signInWithGoogle(): Promise<{ user:User; isAdmin: boolean // Restrict login to only emails from "gecskp.ac.in" // Restrict login to only emails from "gecskp.ac.in", except for a specific admin email -const allowedEmailPattern = /^[a-zA-Z0-9]+@gecskp\.ac\.in$/; -const adminOverrideEmail = "codecompass2024@gmail.com"; + const allowedEmailPattern = /^[a-zA-Z0-9]+@gecskp\.ac\.in$/; + const adminOverrideEmail = "codecompass2024@gmail.com"; -if (user.email !== adminOverrideEmail && !allowedEmailPattern.test(user.email)) { - throw new Error('Only GEC SKP emails are allowed'); -} - - + if (user.email !== adminOverrideEmail && !allowedEmailPattern.test(user.email)) { + throw new Error('Only GEC SKP emails are allowed'); + } - const userDocRef = doc(firestore, 'adminemail', user.email); - const userDoc = await getDoc(userDocRef); + try { + const userDocRef = doc(firestore, 'adminemail', user.email); + const userDoc = await getDoc(userDocRef); - const isAdmin = userDoc.exists() && userDoc.data()?.role === 'admin'; + const isAdmin = userDoc.exists() && userDoc.data()?.role === 'admin'; - return {user, isAdmin }; + return {user, isAdmin }; + } catch (firestoreError) { + console.error('Error accessing Firestore:', firestoreError); + // If Firestore is offline, assume user is not admin for security + return {user, isAdmin: false}; + } } catch (error) { console.error('Error signing in with Google:', error); throw error; } } - - export async function signOutWithGoogle(): Promise { try { await auth.signOut(); diff --git a/lib/firebase/config.ts b/lib/firebase/config.ts index 0c28610..d75f5f4 100644 --- a/lib/firebase/config.ts +++ b/lib/firebase/config.ts @@ -1,6 +1,6 @@ import { initializeApp, getApps, FirebaseApp } from 'firebase/app'; -import { getAuth } from 'firebase/auth'; -import { getFirestore } from 'firebase/firestore'; +import { getAuth, connectAuthEmulator } from 'firebase/auth'; +import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore'; import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage'; const firebaseConfig = { @@ -13,8 +13,6 @@ const firebaseConfig = { measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID, }; - - // Initialize Firebase app export const firebaseApp: FirebaseApp = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0]; @@ -23,6 +21,15 @@ export const auth = getAuth(firebaseApp); export const firestore = getFirestore(firebaseApp); export const storage = getStorage(firebaseApp); +// Enable offline persistence for Firestore +if (typeof window !== 'undefined') { + // Only run on client side + import('firebase/firestore').then(({ enableNetwork, disableNetwork }) => { + // Enable network by default + enableNetwork(firestore); + }); +} + export async function uploadFileToFirebase(file: File, folder: string): Promise { const storageRef = ref(storage, `${folder}/${file.name}`); const snapshot = await uploadBytes(storageRef, file); diff --git a/lib/firebase/firebaseadmin.ts b/lib/firebase/firebaseadmin.ts index 37fdff1..de000d3 100644 --- a/lib/firebase/firebaseadmin.ts +++ b/lib/firebase/firebaseadmin.ts @@ -1,12 +1,25 @@ import admin from 'firebase-admin'; // Initialize Firebase Admin SDK -const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_SDK_KEY as string); +let serviceAccount; +try { + serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_SDK_KEY as string); +} catch (error) { + console.error('Error parsing FIREBASE_ADMIN_SDK_KEY:', error); + throw new Error('Invalid FIREBASE_ADMIN_SDK_KEY format'); +} if (!admin.apps.length) { - admin.initializeApp({ - credential: admin.credential.cert(serviceAccount), - }); + try { + admin.initializeApp({ + credential: admin.credential.cert(serviceAccount), + projectId: serviceAccount.project_id, + }); + console.log('āœ… Firebase Admin initialized successfully'); + } catch (error) { + console.error('Error initializing Firebase Admin:', error); + throw error; + } } export const adminAuth = admin.auth(); diff --git a/test-firebase-admin.js b/test-firebase-admin.js new file mode 100644 index 0000000..2750e4c --- /dev/null +++ b/test-firebase-admin.js @@ -0,0 +1,56 @@ +require('dotenv').config({ path: '.env' }); + +async function testFirebaseAdmin() { + console.log('šŸ”Œ Testing Firebase Admin initialization...'); + + try { + // Test if environment variable is loaded + console.log('šŸ“‹ Environment check:'); + console.log(' FIREBASE_ADMIN_SDK_KEY exists:', !!process.env.FIREBASE_ADMIN_SDK_KEY); + console.log(' FIREBASE_ADMIN_SDK_KEY length:', process.env.FIREBASE_ADMIN_SDK_KEY ? process.env.FIREBASE_ADMIN_SDK_KEY.length : 0); + + // Try to parse the service account + let serviceAccount; + try { + serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_SDK_KEY); + console.log('āœ… Service account parsed successfully'); + console.log(' Project ID:', serviceAccount.project_id); + console.log(' Client Email:', serviceAccount.client_email); + } catch (parseError) { + console.error('āŒ Failed to parse service account:', parseError.message); + return; + } + + // Test Firebase Admin initialization + console.log('\nšŸš€ Testing Firebase Admin initialization...'); + const admin = require('firebase-admin'); + + if (!admin.apps.length) { + admin.initializeApp({ + credential: admin.credential.cert(serviceAccount), + projectId: serviceAccount.project_id, + }); + console.log('āœ… Firebase Admin app initialized'); + } else { + console.log('āœ… Firebase Admin app already exists'); + } + + // Test auth functionality + console.log('\nšŸ” Testing Admin Auth...'); + const adminAuth = admin.auth(); + console.log('āœ… Admin Auth initialized'); + + // Test firestore functionality + console.log('\nšŸ“š Testing Admin Firestore...'); + const adminFirestore = admin.firestore(); + console.log('āœ… Admin Firestore initialized'); + + console.log('\nšŸŽ‰ All Firebase Admin tests passed!'); + + } catch (error) { + console.error('āŒ Firebase Admin test failed:', error.message); + console.error('Stack trace:', error.stack); + } +} + +testFirebaseAdmin(); \ No newline at end of file diff --git a/test-firebase-connection.js b/test-firebase-connection.js new file mode 100644 index 0000000..68b36c6 --- /dev/null +++ b/test-firebase-connection.js @@ -0,0 +1,53 @@ +const { initializeApp } = require('firebase/app'); +const { getFirestore, doc, getDoc } = require('firebase/firestore'); +require('dotenv').config({ path: '.env' }); + +async function testFirebaseConnection() { + console.log('šŸ”Œ Testing Firebase connection...'); + + try { + // Initialize Firebase + const firebaseConfig = { + apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, + authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, + projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, + storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, + messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, + appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID, + }; + + console.log('šŸ“‹ Firebase Config:', { + projectId: firebaseConfig.projectId, + authDomain: firebaseConfig.authDomain, + apiKey: firebaseConfig.apiKey ? 'āœ… Set' : 'āŒ Missing' + }); + + const app = initializeApp(firebaseConfig); + const db = getFirestore(app); + + console.log('āœ… Firebase initialized successfully'); + + // Test Firestore connection + console.log('šŸ” Testing Firestore connection...'); + + try { + // Try to access a document (this will test connectivity) + const testDoc = doc(db, 'test', 'connection-test'); + await getDoc(testDoc); + console.log('āœ… Firestore connection successful'); + } catch (firestoreError) { + if (firestoreError.code === 'failed-precondition') { + console.log('āš ļø Firestore offline - this might be expected in some cases'); + } else if (firestoreError.code === 'unavailable') { + console.log('āŒ Firestore unavailable - check your internet connection'); + } else { + console.log('āŒ Firestore error:', firestoreError.code, firestoreError.message); + } + } + + } catch (error) { + console.error('āŒ Firebase initialization failed:', error.message); + } +} + +testFirebaseConnection(); \ No newline at end of file