Add admin sdk to an existing initialized app - firebase

Is there a way to add admin sdk to an app that's initialized by client firebase already? When I tried to initialize both, it throws an error saying that I can't initialize default app twice. I need client side firebase for login etc, but admin for managing users, both in the same app/website.
What I did so far:
const firebaseConfig = {
...
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
var admin = require("firebase-admin");
admin.initializeApp({
'credentrial': ...
}); //error
var serviceAccount = require("./api_key.json");
var admin_auth = admin.auth();
export { auth, db, admin_auth };
Thanks!

Related

Testing Firebase Cloud Functions: Using admin SDK with jest

What is the best way to use the Firebase admin SDK in jest script to get Firestore information?
I am unable to use the admin SDK in my jest scripts. Running admin.firestore() throws:
Total timeout of API google.firestore.v1.Firestore exceeded 600000 milliseconds before any response was received.
My code:
let issueRefundWix: HttpsCallable<unknown, unknown>,
initApp = async () => {
const serAcc: ServiceAccount = await import(GOOGLE_APPLICATION_CREDENTIALS);
const app = initializeApp(firebaseConfig);
const functions = getFunctions(app, "us-central1");
const db = getFirestore(app);
const auth = getAuth(app);
admin.initializeApp({
credential: admin.credential.cert(serAcc),
storageBucket: "gs://**.appspot.com/",
});
return {
app: app,
functions: functions,
db: db,
auth: auth,
};
};
beforeAll(async () => {
const app = await initApp();
const functions = app.functions;
issueRefundWix = httpsCallable(functions, "issueRefundWix");
db = admin.firestore();
uid = await createWixUser();
exampleSubscription.wixId = uid;
console.log("Finished beforeAll()");
});
This set up works fine when I am running tests on the Firebase Emulator. Can I test functions the same on the emulator as when they are deployed? All tests work fine if I remove any dependencies on admin.firestore().
What is the best way to use the admin SDK to query firestore in jest tests?
Thank you

Firebase CLI: execute arbitrary Firebase Authentication requests to Firebase Emulator

Using the Firebase CLI, I'm executing arbitrary JavaScript that's stored in a file. In that script, I'm trying to make calls to admin.auth().something(), but it doesn't work against the Firebase Emulator. This is in contrast to making calls to Firestore, which works perfectly fine with the Emulator.
Firestore (everything works)
GCP
This makes calls to Firestore on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
const db = admin.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Emulator
This also succeeds:
const admin = require('#firebase/testing');
const db = admin
.initializeAdminApp({ projectId: 'my-project' })
.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Firebase Auth (GCP works but Emulator does not)
GCP
This makes calls to Firebase Auth on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
(async () => {
const user = await admin
.auth()
.getUser('user123456789');
console.log(user.email);
})();
Emulator
This fails:
const admin = require('#firebase/testing');
const auth = admin
.initializeAdminApp({ projectId: 'my-project' })
.auth();
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();
The error message is:
C:\Users\...\node_modules\#firebase\testing\node_modules\#firebase\component\dist\index.cjs.js:134
throw e;
^
[t [Error]: Your API key is invalid, please check you have copied it correctly.] {
code: 'auth/invalid-api-key',
a: null
}
I'm not sure what API key they're referring to, as the request is against the Emulator. How can I execute Firebase Auth requests against the Emulator using Firebase CLI?
To send requests against Firebase Emulator Auth, set the following environment variables and use the standard Firebase Admin SDK (firebase-admin) instead of using #firebase/testing:
process.env.FIREBASE_AUTH_EMULATOR_HOST = 'localhost:9099';
process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080';
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'emulator projectId' });
Now this works:
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();

Firebase Admin Module Not Found Can't Resolve '#firebase/app' NextJs

I am working on a project that is using Vercel's NextJS build with Firebase Hosting. I've added Firebase functions which I have working well. In the firebaseFunctions.js file I created an export so that I could share the connection to Firebase with other files. However, when trying to use the export I am getting the following error.
The file structure of the project looks like the following.
The following file is the firebaseFunctions.js file that includes the Firebase app initialization and Firestore initialization. All code in this file works when using functions or trying to connect to Firestore.
const { join } = require('path'); // From NextJS Vercel Base Build
const { default: next } = require('next'); // From NextJS Vercel Base Build
const isDev = process.env.NODE_ENV !== 'production'; // From NextJS Vercel Base Build
const nextjsDistDir = join('src', require('./src/next.config.js').distDir); // From NextJS Vercel Base Build
const admin = require('firebase-admin'); // Firebase Admin SDK for NodeJS.
const functions = require('firebase-functions'); // For NextJS + Firebase Functions + Firebase Hosting.
const serviceAccount = require('./serviceAccountKey.json'); // Service account key for Firebase Admin SDK.
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
const db = admin.firestore();
const nextjsServer = next({
dev: isDev,
conf: {
distDir: nextjsDistDir,
},
});
const nextjsHandle = nextjsServer.getRequestHandler();
// Nextjs Cloud Function to allow for Firebase Hosting.
exports.nextjsFunc = functions.https.onRequest((req, res) => {
return nextjsServer.prepare().then(() => nextjsHandle(req, res));
});
exports.getCustomToken = functions.https.onCall(async (data, context) => {
// Do something here.
});
module.exports.admin = admin;
module.exports.db = db;
You can see that I export both admin and db here.
In CreateTimer I require db. However this does not allow me access to db.
const db = require('./../firebase/firebase');
Any help with why this may be would be appreciated.
I've done the following.
Verified that Firebase is installed.
Tested Firebase from firebaseFunctions.js
My issue was that I was trying to use the Firebase Admin SDK with React which is a front side language. Firebase Admin can only be used with backend environment like Nodejs. I created a web project in Firebase and then configured this for use in the app.

Unable to send or retrive data in the Firebase Web

I am facing a problem in sending or retrieving the data from the Firebase web.
Although I can successfully register the user and I can even get the user UID by writing the code shown below-
if(user!=null)
{
var uid = firebase.auth().currentUser.uid;
console.log(`UID ===> ${uid}`)
}
But still I cannot retrieve/send data from/to the Firebase. I am not even getting any error in the console.
My codes for index.js file in the functions folder is below-
const functions = require('firebase-functions');
const express = require('express');
var admin = require('firebase-admin');
var serviceAccount = require('/path/to/my/serviceAccount/key.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://urlOfMyDatabaseURL.firebaseio.com'
});
const app = express();
app.get('/', (request, response)=>{
response.send(index.html);
});
exports.app=functions.https.onRequest(app);
Please help, I am stuck here!

firebase cloud functions failed to access google sheet api

I want to build an api service that use google sheet api to create, read and write the spreadsheets. The api service is deployed on firebase cloud functions with express.js, I have created the service account, and use JWT for authentication. The api works (i.e. can create, read and write spreadsheets) when test locally, but fails when I deployed to firebase cloud functions.
const functions = require('firebase-functions');
// firebase admin
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// google sheet api
const google = require('googleapis');
const key = require('./key/serviceKey.json');
const scopes = [
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive'
];
const authClient = new google.auth.JWT(
key.client_email, null, key.private_key, scopes, null
);
authClient.authorize((err, tokens) => {
if (err) {
console.log('error occurred when authorising with JWT');
} else {
console.log('auth success, tokens', tokens);
google.options({ auth: authClient });
}
});
const drive = google.drive('v2');
const sheets = google.sheets('v4');
The error message I get when I test it on firebase cloud functions:
Request is missing required authentication credential. Expected OAuth
2 access token, login cookie or other valid authentication credential.
Ultimately, I will have an ionic app that calls the api to perform certain actions (e.g. create and share spreadsheets with other user). So am I doing the right approach or I should use other types of authentication?
My function definitions:
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')({ origin: true });
const bodyParser = require('body-parser');
const app = express();
app.use(cors);
app.use(bodyParser.json({ type: 'application/json' }));
// some routing setup
exports.api = functions.https.onRequest(app);
Router setup:
const express = require('express');
const router = express.Router();
router.post('/createSheets', (req, res) => {
const request = { // }
sheets.spreadsheets.create(request, (err, sheetsResponse) => {
// some code
}
});

Resources