firebase DB and express - node.js

I'm trying to connect my firebase data to express in a similar way I would with a data.json file - am I doing this correctly?
I'm getting a "Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail" error that I'm nto quite sure how to fix - I also found an article that seems like Firebase can be accessed all in the front end so maybe I don't need to use express?
const express = require('express');
const app = express();
const port = process.env.PORT || process.argv[2] || 8080
const bodyParser = require('body-parser');
// const data = require('./data.json');
const cors = require('cors');
const firebase = require('firebase-functions');
const admin = require('firebase-admin');
const config = require('./config');
const db = firebase.initializeApp(config);
const serviceAccount = require('./serviceAccount.json');
require('dotenv').config();
app.use(cors());
app.use(bodyparser.urlencoded({extended: true}));
app.options('*', cors());
app.use(bodyParser.json());
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://wheresthespot-f83b8.firebaseio.com'
});
app.get('/locations', (req, res) => {
res.send(db)
})
app.get('/location/:name', (req, res) => {
res.send(b)
})
app.post('location', (req, res) => {
const { id, location, description, morningLight, eveningLight, address, city, region, longitude, latitude, categories, permit } = req.body
const newLocation = {
id,
location,
description,
morningLight,
eveningLight,
address,
city,
region,
longitude,
latitude,
categories,
permit
}
res.json([
db.locations,
newLocation
])
db.locations.push(newLocations);
})
app.listen(port, () => console.log(`We're live on port, ${port}`))
module.exports.db = db.database();```

In order to use the Firebase Admin SDK effectively, you should start with the instructions. In particular, you will need to figure out how you would like to initialize the SDK. If you are running your own node server, you will need to provide credentials for your Firebase project as shown in that documentation.
We can't see exactly what you're doing now, since we don't know what's in './config'. The documentation suggests setting the environment variable "GOOGLE_APPLICATION_CREDENTIALS" to point to the file with your service account credentials. You will not be able to use the configuration for web or mobile applications - you must use a service account.

Related

cookie are not set in browser when I am use the node as backend

Cookies are not set in browser. I am use the node as backend. I am try to search problem some person tell that's cookies will not setting because of I am using react as front and node as backed both are run on same virtual server that is localhost. That why it happen.
this is my code please help.
User.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const RegisterModel = require("../Model/RegisterModel")
const signIn = async (req,res)=>{
try {
const data = await RegisterModel.findOne({Email:req.body.email})
const passwordMatch = await bcrypt.compare(req.body.password,data.Password)
const token = await jwt.sign({Email : data.Email}, process.env.SECRET)
if(!data) return res.status(404).json({islogin:false, message: "User doesn't exist" })
if(!passwordMatch) return res.status(400).json({islogin:false,message: "Incorrect Password"})
if(passwordMatch){
res.cookie('newToken',token, { maxAge: 900000, httpOnly: false});
res.status(200).send({id:data._id,email:data.Email,name:data.Name,islogin:true,token:token})
}
} catch (error) {
res.status(404).json({islogin:false,message:"User doesn't exist"})
console.log(error)
}
}
module.exports = {signIn,signUp};
app.js
const express = require('express');
var cookieParser = require('cookie-parser')
const app = express();
app.use(cookieParser())
const dotenv = require('dotenv');
dotenv.config()
var cors = require('cors')
const PORT = process.env.PORT ;
const router = require("./Router/Router")
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended:false}));
app.use(router);
require("./Connection/Connection")
app.listen(PORT,()=>{
console.log(`Listen at Port ${PORT}` )
})
for set credentials data into browser it is necessary to run both side on same domain backend should be run on localhost or 127.0.0.1 and frontend should be run on localhost or 127.0.0.1 respectively.
or
backend and frontend run on =localhost or
backend and frontend run on =127.0.0.1
if you are not sure then issue error's show on console. here
browser suggest you error regarding cookies.
also set cors policy on backend side like =
cors({origin:"http:localhost:frontendPORT", credentials:true})
frontend side on http request, must be set with credentials= true
this method work for me after spending 4 days.

Store webhooks functions inside a master function

I have set up multiple webhook endpoints that follow the similar structure in Node.js: 1) stringify the JSON request and 2) do something about that stringified request in R.
This consequently leads to a lot of duplicate code, and I attempt to stay DRY by creating a function in which I specify the arguments that actually do change. Here's an example.
First, the top portion of the script:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
Then, the part I would like to rewrite into a master function (WH) in which everything capitalized below between < and > becomes the argument.
app.post(<ENDPOINT>, foobar);
function foobar(req, res) {
var spawn = require("child_process").spawn;
let body = JSON.stringify(req.body);
var R_shell = spawn("/usr/local/bin/Rscript", [<PATH_TO_SCRIPT>, body]);
res.end("Processing completed");
}
app.get(<ENDPOINT>, (req, res) => res.send(`<html><body><h1>All working!</h1></body></html>
`));
Hence, with two endpoints, I'd end up with:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
WH(endpoint="foo", script_path="baz")
WH(endpoint="lorem", script_path="dolor")
P.S. Sorry if this is poorly formulated question from a Node.js standpoint—it's my first time developing with Node.js.
If I understood your question correctly, what you can do is something like this:
Firstly, you need to create a function that returns a router with the specified routes (You could create this function in a different file to make the code cleaner).
const {Router} = require('express')
function WH(endpoint, scriptPath) {
const router = Router()
function fn(req, res) {
var spawn = require("child_process").spawn;
let body = JSON.stringify(req.body);
var R_shell = spawn("/usr/local/bin/Rscript", [scriptPath, body]);
res.end("Processing completed");
}
router.post(endpoint, fn);
router.get(endpoint, (req, res) => res.send(`<html><body><h1>All working!</h1></body></html>`));
return router
}
And finally you should use it like this:
require("dotenv").config();
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
app.use(WH("/foo", "./baz"))
app.use(WH("/lorem", "./dolor"))

swagger-ui-express Multiple Routes for Different API Documentation

I have 2 separate swagger API documentations which I want to run via swagger-ui-express NPM package, and my express server is starting fine on port 5000, but when I am trying to access any of the URL always getting the 404 error, Here is my app.js file and URL's for your reference:
Route 1: http://localhost:5000/edi
Route 2: http://localhost:5000/ecom
const express = require('express');
const router = require('express').Router();
const swaggerUi = require('swagger-ui-express');
const ediSwaggerDocument = require('./edi-openapi.json');
const ecomSwaggerDocument = require('./ecom-openapi.json');
const SWAGGER_APP_PORT = process.env.SWAGGER_APP_PORT || 5000;
const app = express();
// Route Middleware to be called before serving Any Route
router.use('/', swaggerUi.serve);
// Route - EDI RESTful API Documentaion
router.get('/edi', swaggerUi.setup(ediSwaggerDocument));
// Route - eCommerce RESTful API Documentaion
router.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));
app.listen(SWAGGER_APP_PORT, () => console.log(`RESTful API Up and Running on Port ${SWAGGER_APP_PORT}`));
Try the following configurations to hook swaggerUi with express-app
app.use("/edi", swaggerUi.serve, (...args) => swaggerUi.setup(ediSwaggerDocument)(...args));
app.use("/ecom", swaggerUi.serve, (...args) => swaggerUi.setup(ecomSwaggerDocument)(...args));
I haven't dig enough into the swagger-ui-express but i think the problem comes from the function generateHTML (called in swaggerUi.setup). A global module variable (swaggerInit) is updated when called.
So the last call to generateHTML has side effects on every routes that use swaggerUi.setup middleware.
A quick fix is to generate HTML each time the route is called. According to the code snippet you provide, it should looks like :
let swaggerDocEdi = require('./edi-openapi.json');
let swaggerDocEcom= require('./ecom-openapi.json');
let router = express.Router();
router.use('/api/edi', swagger.serve, (req, res) => {
let html = swagger.generateHTML(swaggerDocEdi);
res.send(html);
});
router.use('/api/ecom', swagger.serve, (req, res) => {
let html = swagger.generateHTML(swaggerDocEcom);
res.send(html);
});
Note that the global variable is still updated.
router.use('/jobs/api/:id',swaggerUi.serve,(req,res)=>{
console.log("here")
let a = req.params.id
if(a==='all'){ res.status(200).send(swaggerUi.generateHTML(swaggerDocument))}
if(a==='google'){res.status(200).send(swaggerUi.generateHTML(GoogleAds)) }
});
I was also looking for a solution for this issue, and found a better solution recommended by Swagger UI Express. check the link below
https://github.com/scottie1984/swagger-ui-express#two-swagger-documents
const express = require('express');
const app = express();
const swaggerUi = require('swagger-ui-express');
const swaggerDocumentOne = require('./swagger-one.json');
const swaggerDocumentTwo = require('./swagger-two.json');
var options = {}
app.use('/api-docs-one', swaggerUi.serveFiles(swaggerDocumentOne, options), swaggerUi.setup(swaggerDocumentOne));
app.use('/api-docs-two', swaggerUi.serveFiles(swaggerDocumentTwo, options), swaggerUi.setup(swaggerDocumentTwo));
Hope this will help others as well.
It looks like the Router is being used incorrectly. For this simple use case I would recommend adding your routes directly to the app instance. See:
const express = require('express');
// xxxx const router = require('express').Router();
const swaggerUi = require('swagger-ui-express');
const ediSwaggerDocument = require('./edi-openapi.json');
const ecomSwaggerDocument = require('./ecom-openapi.json');
const SWAGGER_APP_PORT = process.env.SWAGGER_APP_PORT || 5000;
const app = express();
// Route Middleware to be called before serving Any Route
app.use('/', swaggerUi.serve); // replaced router with app
// Route - EDI RESTful API Documentaion
// REPLACED "router" with "app"
app.get('/edi', swaggerUi.setup(ediSwaggerDocument));
// Route - eCommerce RESTful API Documentaion
// REPLACED "router" with "app"
app.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));
app.listen(SWAGGER_APP_PORT, () => console.log(`RESTful API Up and Running on Port ${SWAGGER_APP_PORT}`));
Now, you could use the Router by adding it to the app instance with app.use(). See:
// Route - EDI
router.get('/edi', swaggerUi.setup(ediSwaggerDocument));
// Route - eCommerce
router.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));
// Adding it to App instance
app.use('/swagger', router)
// End Point => localhost:5000/swagger/edi
Hope this helps!!

ExpressJS Middleware Method to make variable available in other (module) files

I am playing around with making a NodeJS app that combines REST API functionality with MongoDB CRUD persistence. I'm pretty new to NodeJS.
Right now I've managed to connect to the Database and figured out that the rest of my code belongs inside the callback - ie only process REST request after the DB is up and available.
The challenge I'm running into in this case is understanding how to "attach" the 'client' (from mongodb.connect) to the 'request'. I need to somehow make it available in other files because I want to keep my routes separate as a best practice.
The same question applies to any variables in the main server.js file which I need to be able to access in my modules.
Here is the relevant code:
//server.js
const express = require('express')
const mongodb = require('mongodb')
const bodyParser = require('body-parser')
const routes = require('./routes')
const url = 'mongodb://localhost:27017/testDB'
let app = express();
app.use(logger('dev'))
app.use(bodyParser.json())
mongodb.connect(url, {useNewUrlParser:true},(error, dbClient) => {
if (error) {
console.log(`Error: ${error}`)
process.exit(1)
}
//connected
console.log(`Connected to mongoDB`)
//what do I do here to make sure my routes can access dbClient?
app.get('/accounts', routes.getAccounts(req, res) )
app.listen(3000)
})
//./routes/index.js
const bodyParser = require('body-parser')
const errorhandler = require('errorhandler')
const mongodb = require('mongodb')
const logger = require('morgan')
module.exports = {
getAccounts: (req, res) => {
console.log("in getAccounts")
//how can I use dbClient in here?
}
}
Thank you in advance for your help!
My apologies if anything about my post isn't according to the normal standards, I'm brand new here! All critique appreciated, coding and otherwise!

Trying to access configured const across express router files

I'm new to node js so this might be a simple question. In my index.js file I have configured an imported module admin, and I wish to use this configuration across my routed files. How do I pass/access this configured constant? I don't want to have to configure it in every single file.
// In index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require("express")
const myApi = require("./api/my")
admin.initializeApp(functions.config().firebase);
const app = express();
app.use("/api/my", myApi.myRouter);
// In ./api/my/index.js
const myRouter = express.Router();
myRouter.get('/account', function(req, res) {
admin.auth().... <- Need to use the previously configured admin here
}
You can use a top level middleware to define admin property inside the req object:
app.use( function (req, res, next) {
req.admin = admin;
next();
});
Now the fireBase instance is available in any route handler via req.admin
Another approach consist of passing the admin const when you requiring the router file:
index.js:
const myApi = require("./api/my")(admin)
Router file:
const myRouter = express.Router();
module.exports = function (admin) {
myRouter.get('/account', function(req, res) {
admin.auth()....
}
return myRouter;
}
Another way is to use app.set() to store a reference to the admin object and app.get() to get that reference:
index.js
const admin = require('firebase-admin');
app.set('admin', admin);
Router file:
myRouter.get('/account', function(req, res) {
const admin = req.app.get('admin');
admin.auth()....
}
You can make it global .
global.admin = require('firebase-admin');
This can be used across routed files .
But I recommend you to import in every file because global declaration clutter up the global namespace and are slower to look up than local variables.

Resources