Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/api/projects/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';


Expand Down Expand Up @@ -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;

Expand Down
49 changes: 49 additions & 0 deletions check-db.js
Original file line number Diff line number Diff line change
@@ -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();
4 changes: 2 additions & 2 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/db.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
34 changes: 19 additions & 15 deletions lib/firebase/auth.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;

Expand All @@ -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 = "[email protected]";
const allowedEmailPattern = /^[a-zA-Z0-9]+@gecskp\.ac\.in$/;
const adminOverrideEmail = "[email protected]";

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<void> {
try {
await auth.signOut();
Expand Down
15 changes: 11 additions & 4 deletions lib/firebase/config.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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];
Expand All @@ -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<string> {
const storageRef = ref(storage, `${folder}/${file.name}`);
const snapshot = await uploadBytes(storageRef, file);
Expand Down
21 changes: 17 additions & 4 deletions lib/firebase/firebaseadmin.ts
Original file line number Diff line number Diff line change
@@ -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();
Expand Down
56 changes: 56 additions & 0 deletions test-firebase-admin.js
Original file line number Diff line number Diff line change
@@ -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();
53 changes: 53 additions & 0 deletions test-firebase-connection.js
Original file line number Diff line number Diff line change
@@ -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();