const functions = require('firebase-functions') let express = require('express') let logger = require('morgan') let bodyParser = require('body-parser') let admin = require("firebase-admin") let serviceAccount = require("./project-gg-3b754-firebase-adminsdk-4848h-5a5778b77b.json") let firebaseadmin = admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://project-gg-3b754.firebaseio.com" }) let database = firebaseadmin.database() let app = express() app.use(bodyParser.urlencoded({extended: true})) app.use(bodyParser.json()) app.use(logger('dev')) app.use(express.static('views')) app.set('view engine', 'ejs') app.set('views', __dirname + '/views') let nodemailer = require('nodemailer') let transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: 'noreply.projectgg@gmail.com', pass: 'kynpef-5paqha-xaVxip' } }) app.get("/", function(request, responce) { homePage(request, responce) }) app.get("/home", function(request, responce) { homePage(request, responce) }) function homePage(request, responce) { var dbRef = database.ref("/products") dbRef.orderByChild("status").equalTo("on-sale").limitToLast(5).once('value', function(snapshot){ var data = {} if (snapshot.val()) {data = snapshot.val()} responce.render('home.ejs', {products: data}) }) } app.get('/search', function(request, responce){ var dbRef = database.ref("/products") if (request.query.search) { let sQuery = request.query.search.toLowerCase() dbRef.orderByChild("status").equalTo("on-sale").once('value', function(snapshot){ var data = {'x': {name: 'Nothing found 😢',price: ''}} if (snapshot.val()) { data = snapshot.val() var sResults = [{name: 'Nothing found 😢',price: ''}] var keys = Object.keys(data) keys.forEach(key => { if (data[key].name.toLowerCase().includes(sQuery) || data[key].desc.toLowerCase().includes(sQuery)) {sResults[key] = data[key]} }) if (Object.keys(sResults).length > 1) {delete sResults[0]} responce.render('search.ejs', {products: sResults}) } else {responce.render('search.ejs', {products: data})} }) } else { dbRef.orderByChild("status").equalTo("on-sale").once('value', function(snapshot){ var data = {'x': {name: 'Nothing found 😢',price: ''}} if (snapshot.val()) {data = snapshot.val()} responce.render('search.ejs', {products: data}) }) } }) app.get('/admin-review', async function(request, responce){ var dbRef = database.ref("/products") if (request.query.authToken) { let uid = await authCheck(request.query.authToken) if (uid == "If84zSzRvlcCqRs0ZPJRpAcY1He2") { dbRef.orderByChild("status").equalTo("pending").once('value', function(snapshot){ if (snapshot.exists()) { let products = snapshot.val() responce.render('admin-review.ejs', {products: products}) } else { var products = {'x': {name: 'Nothing to review...',price: ''}} responce.render('admin-review.ejs', {products: products}) } }) } else { responce.render('404.ejs') } } else { responce.render('404.ejs') } }) app.get('/additmpage', function(request, responce){ responce.render('add-item.ejs') }) app.get('/my-products', function(request, responce){ if (request.query.uToken) { admin.auth().verifyIdToken(request.query.uToken) .then(function(decodedToken) { let uid = decodedToken.uid var dbRef = database.ref("/products") if (uid == "If84zSzRvlcCqRs0ZPJRpAcY1He2") { dbRef.orderByChild('owner').once('value', function(snapshot){ var data = snapshot.val() responce.render('my-products.ejs', {products: data}) }) } else { dbRef.orderByChild('owner').equalTo(uid).once('value', function(snapshot){ var data = {'x': {holder: '',id: 999,img: '',location: '',name: 'No products listed 😢',owner: '',price: '',stock: ''}} if (snapshot.val()) {data = snapshot.val()} responce.render('my-products.ejs', {products: data}) }) } }) .catch(function(error) { console.log(error) responce.send("

Bad Auth Token

Home") }) } else { responce.send("

No Auth Token Provided

Home") } }) app.get('/my-product', function(request, responce){ if (request.query.uToken && request.query.productid) { admin.auth().verifyIdToken(request.query.uToken) .then(async function(decodedToken) { let uid = decodedToken.uid let pid = request.query.productid if (await verifyExists(pid)){ if (await verifyOwner(uid, pid)) { var dbRef = database.ref("/products/"+pid) dbRef.once('value', function(snapshot){ data = snapshot.val() responce.render('my-product.ejs', {item:data, key:pid}) }) } else { responce.render('404.ejs') } } else { responce.render('404.ejs') } }) .catch(function(error) { console.log(error) responce.send("

Bad Auth Token

Home") }) } else { responce.send("

No Auth Token Provided

Home") } }) app.get('/edit-item', function(request, responce){ if (request.query.uToken && request.query.productid) { admin.auth().verifyIdToken(request.query.uToken) .then(async function(decodedToken) { let uid = decodedToken.uid let pid = request.query.productid if (await verifyExists(pid)){ if (await verifyOwner(uid, pid)) { let dbRef = database.ref("/products/"+pid) dbRef.once('value', function(snapshot){ data = snapshot.val() responce.render('edit-item.ejs', {item:data, key:request.query.productid}) }) } else { responce.render('404.ejs') } } else { responce.render('404.ejs') } }) .catch(function(error) { console.log(error) responce.send("

Bad Auth Token

Home") }) } else { responce.send("

No Auth Token Provided

Home") } }) app.get('/product', function(request, responce){ if (request.query.productid) { var dbRef = database.ref("/products/"+request.query.productid) dbRef.once('value', function(snapshot){ data = snapshot.val() if (data){ sellerID = data.owner let sellerName = "John Doe (error)" let usersRef = database.ref("/users") usersRef.orderByChild("UID").equalTo(sellerID).once('value', function(snapshot){ vals = snapshot.val() var keys = Object.keys(vals) uData = vals[keys[0]] sellerName = uData.fName + " " + uData.lName sellerDBID = keys[0] responce.render('product.ejs', {item:data, key:request.query.productid, seller:{name:sellerName, dbid:sellerDBID}}) }) .catch(e => {console.log(e)}) } else { responce.render('404.ejs') } }) } else { responce.render('404.ejs') } }) app.get('/user-profile', function(request, responce){ if (request.query.dbid) { var dbRef = database.ref("/users/" + request.query.dbid) dbRef.once('value', function(snapshot){ user = snapshot.val() if (user){ let productsRef = database.ref("/products") let userProfile = { name: user.fName + " " + user.lName, location: user.address, rating: "WIP", memberSince: user.memberSince, pPic: user.pPic } productsRef.orderByChild("owner").equalTo(user.UID).once('value', function(snapshot){ if (snapshot.exists()) { let allProductsDict = snapshot.val() let allProductsKeys = Object.keys(allProductsDict) let filteredKeys = allProductsKeys.filter(function( obj ) { return allProductsDict[obj].status == 'on-sale'; }) let filteredProducts = {"0":{img: '',name: 'Nothing listed 😢',price: ''}} filteredKeys.forEach(function(key){filteredProducts[key] = allProductsDict[key]}) if (Object.keys(filteredProducts).length > 1) {delete filteredProducts["0"]} responce.render('user-profile.ejs', {userProducts:filteredProducts, user:userProfile, userDBID:request.query.dbid}) } else { responce.render('user-profile.ejs', {userProducts:[], user:userProfile, userDBID:request.query.dbid}) } }) .catch(e => { console.log(e) responce.render('404.ejs') }) } else { responce.render('404.ejs') } }) .catch(e => { console.log(e) responce.render('404.ejs') }) } else { responce.render('404.ejs') } }) app.get('/registration', function(request, responce){ responce.render('user-registration.ejs') }) app.post('/register-new-user-api', async function(request, responce){ let rBody = request.body if (rBody.authToken && rBody.data.fName && rBody.data.lName && rBody.data.address && rBody.data.pPic) { let uid = false decodedToken = await admin.auth().verifyIdToken(rBody.authToken).catch(e=>{console.log(e)}) uid = decodedToken.uid email = decodedToken.email if (uid) { if (await checkUserExists(uid) == false) { let fName = rBody.data.fName let lName = rBody.data.lName let address = rBody.data.address let pPic = rBody.data.pPic let today = new Date() let month = today.toLocaleString('default', { month: 'long' }) let year = today.getFullYear() let uData = { fName:fName, lName:lName, UID:uid, email:email, address:address, pPic:"x", memberSince: month + " " + year } let usersRef = database.ref('/users') let result = await usersRef.push(uData) let key = result.key let imgPath = "/user-img/" + key + '/' + pPic ///this is problematic let userRef = database.ref('/users/' + key) userRef.update({pPic:imgPath}) .then(responce.send({success:true, error:null, imgRef:imgPath})) .catch(e=>{ responce.send({success:false, error:e}) }) } else { responce.send({success:false, error:'user exists'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({success:false, error:'invalid data'}) } }) app.post('/contact-api', async function(request, responce){ if (request.body.userDBID && request.body.authToken && request.body.usrMsg) { let bMsg = request.body.usrMsg let sellerDBID = request.body.userDBID let uid = await authCheck(request.body.authToken) if (uid) { let usersRef = database.ref("/users") snapshot = await usersRef.orderByChild("UID").equalTo(uid).once('value') if (snapshot.exists()) { let vals = snapshot.val() let keys = Object.keys(vals) let user = vals[keys[0]] let userEmail = user.email let userName = user.fName + ' ' + user.lName let sellerRef = database.ref("/users/" + sellerDBID) snapshot = await sellerRef.once('value') if (snapshot.exists()) { let seller = snapshot.val() let sellerName = seller.fName let sellerEmail = seller.email let content = sellerMessageContentMaker(sellerName, userName, userEmail, bMsg) let subject = 'New message!' sendEmail(sellerEmail, subject, content) responce.send({success:true, error:null}) } else { responce.send({success:false, error:'User does not exist!'}) } } else { responce.send({success:false, error:'Unregistered user!'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({success:false, error:'invalid data'}) } }) app.post('/request-api', async function(request, responce){ if (request.body.prodID && request.body.authToken && request.body.usrMsg) { let bMsg = request.body.usrMsg let uid = await authCheck(request.body.authToken) if (uid) { let pid = request.body.prodID let productRef = database.ref("/products/"+ pid) var snapshot = await productRef.once('value') if (snapshot.exists()) { let product = snapshot.val() let productName = product.name let productSeller = product.owner let usersRef = database.ref("/users") snapshot = await usersRef.orderByChild("UID").equalTo(productSeller).once('value') if (snapshot.exists()) { let vals = snapshot.val() let keys = Object.keys(vals) let seller = vals[keys[0]] let sellerName = seller.fName let sellerEmail = seller.email snapshot = await usersRef.orderByChild("UID").equalTo(uid).once('value') if (snapshot.exists()) { let vals = snapshot.val() let keys = Object.keys(vals) let buyer = vals[keys[0]] let buyerName = buyer.fName + ' ' + buyer.lName let buyerEmail = buyer.email let content = contentMaker(sellerName, buyerName, buyerEmail, productName, pid, bMsg) let subject = 'Someone\'s interested!' sendEmail(sellerEmail, subject, content) responce.send({success:true, error:null}) } else { responce.send({success:false, error:'Unregistered user!'}) } } else { responce.send({success:false, error:'Something very bad has happened..... Item owner apparantly doesn\'t exist in the database'}) } } else { responce.send({success:false, error:'Item does not exist'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({success:false, error:'invalid data'}) } }) app.post('/toggle-sale-api', async function(request, responce){ if (request.body.prodID && request.body.authToken && (request.body.targetState != null)) { let uid = await authCheck(request.body.authToken) if (uid) { let productID = request.body.prodID let targetState = request.body.targetState let productRef = database.ref("/products/"+ productID) var snapshot = await productRef.once('value') if (snapshot.exists()) { let product = snapshot.val() if (await verifyOwner(uid, productID) && (product.status == "on-sale" || product.status == "off-sale")) { let status = "x" if (targetState == true) { status = "on-sale" } else { status = "off-sale" } productRef.update({status:status}) .then(responce.send({success:true, error:null})) .catch(e => {responce.send({success:false, error:e})}) } else { responce.send({success:false, error:'Unauthorized'}) } } else { responce.send({success:false, error:'Item does not exist'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({success:false, error:'invalid data'}) } }) app.post('/sold-api', async function(request, responce){ if (request.body.prodID && request.body.authToken) { let uid = await authCheck(request.body.authToken) if (uid) { let productID = request.body.prodID let productRef = database.ref("/products/"+ productID) var snapshot = await productRef.once('value') if (snapshot.exists()) { if (await verifyOwner(uid, productID)) { productRef.update({status:"sold"}) .then(responce.send({success:true, error:null})) .catch(e => {responce.send({success:false, error:e})}) } else { responce.send({success:false, error:'Unauthorized'}) } } else { responce.send({success:false, error:'Item does not exist'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({success:false, error:'invalid data'}) } }) app.post('/login-user-api', function(request, responce){ if (request.body.uToken) { admin.auth().verifyIdToken(request.body.uToken) .then(async function(decodedToken) { let uid = decodedToken.uid let rsp = await processUserStatus(uid) responce.send(rsp) }) .catch(e=>{ responce.send({success:false, error:'invalid auth token, ' + e}) }) } else { responce.send({success:false, error: 'invalid data'}) } }) app.post('/shipping-adress-edit-api', function(request, responce){ if (request.body.authToken && request.body.address) { admin.auth().verifyIdToken(request.body.authToken) .then(async function(decodedToken) { let newAddress = request.body.address let uid = decodedToken.uid let snapshot = await checkUserExists(uid) if (snapshot){ let users = snapshot.val() var keys = Object.keys(users) userKey = keys[0] userRef = database.ref("/users/"+userKey) userRef.update({address:newAddress}) .then(function(){ responce.send({success:true, error:null}) }) } else { responce.send({success:false, error:'user does not exist'}) } }) .catch(function(error) { responce.send({success:false, error:'invalid auth token'}) console.log(error) }) } else { responce.send({success:false, error: 'invalid data'}) } }) app.post('/product-ar-api', async function(request, responce){ if (request.body.authToken && request.body.prodID && (request.body.approved != null)) { let uid = await authCheck(request.body.authToken) if (uid == "If84zSzRvlcCqRs0ZPJRpAcY1He2") { var productStatus = "rejected" if (request.body.approved == true) {productStatus = "on-sale"} productRef = database.ref("/products/" + request.body.prodID) let snapshot = await productRef.once('value') if (snapshot.exists()) { productRef.update({status:productStatus}) .then(responce.send({success:true, error: null})) .catch(e=>{responce.send({success:false, error: e})}) } else { responce.send({success:false, error: 'Item does not exist'}) } } else { responce.send({success:false, error: 'Unauthorized'}) } } else { responce.send({success:false, error: 'invalid data'}) } }) app.post('/shipping-adress-get-api', function(request, responce){ if (request.body.authToken) { admin.auth().verifyIdToken(request.body.authToken) .then(async function(decodedToken) { let uid = decodedToken.uid let snapshot = await checkUserExists(uid) if (snapshot){ let users = snapshot.val() var keys = Object.keys(users) let user = users[keys[0]] let userAddress = user.address responce.send({success:true, error:null, address:userAddress}) } else { responce.send({success:false, error:'user does not exist'}) } }) .catch(function(error) { responce.send({success:false, error:'invalid auth token'}) console.log(error) }) } else { responce.send({error: 'invalid data'}) } }) app.post('/new-product-api', async function(request, responce){ if (request.body.authToken && request.body.product && request.body.image) { let uid = await authCheck(request.body.authToken) if (uid) { if (await checkUserExists(uid)) { let image = request.body.image let product = request.body.product let imageName = image.name product.status = "pending" let newProductRef = database.ref('/products') newProductRef.push(product).then(key => { let productKey = key.key let imgPath = '/product-img/' + productKey + '/' + imageName ///this is problematic let productRef = database.ref('/products/' + productKey) productRef.update({img: imgPath}).then(function(){ responce.send({success:true, imgRef:imgPath, error:null}) }) .catch(e=>{ responce.send({success:false, error:e}) console.log(error) }) }) .catch(e=>{ responce.send({success:false, error:e}) console.log(error) }) } else { responce.send({success:false, error:'Unregistered!'}) } } else { responce.send({success:false, error:'invalid auth token'}) } } else { responce.send({error: 'invalid data'}) } }) app.post('/update-product-api', function(request, responce){ if (request.body.authToken && request.body.product && request.body.productID) { admin.auth().verifyIdToken(request.body.authToken) .then(async function(decodedToken) { let uid = decodedToken.uid let product = request.body.product let productID = request.body.productID if (await verifyExists(productID)){ if (await verifyOwner(uid, productID)) { let productRef = database.ref('/products/' + productID) productRef.update(product).then(function(){ responce.send({success:true, error:null}) }) .catch(e=>{ responce.send({success:false, error:e}) console.log(error) }) } else { responce.send({success:false, error:'You do not own this item'}) } } else { responce.send({success:false, error:'Item does not exist'}) } }) .catch(function(error) { responce.send({success:false, error:'invalid auth token'}) console.log(error) }) } else { responce.send({error: 'invalid data'}) } }) function contentMaker(sName, bName, bEmail, pName, pid, bMsg){ let text = "Hi " + sName + "\n \n" + bName + " is interested in your product " + pName + " (ID: " + pid + ")\n\nUser email: " + bEmail +"\n\nUser message:\n" + bMsg return text } function sellerMessageContentMaker(sName, bName, bEmail, bMsg){ let text = "Hi " + sName + "\n \n" + bName + " would like to send you a message.\n\nUser email: " + bEmail +"\n\nMessage:\n" + bMsg return text } async function authCheck(token) { let uid = false decodedToken = await admin.auth().verifyIdToken(token).catch(e=>{console.log(e)}) uid = decodedToken.uid return uid } async function processUserStatus(uid){ let snapshot = await checkUserExists(uid) if (snapshot){ let users = snapshot.val() let keys = Object.keys(users) let uData = users[keys[0]] let uName = uData.fName let retData = {success:true, registered:true, name:uName} return retData } else { let retData = {success:true, registered:false} return retData } } async function checkUserExists(uid){ var dbRef = database.ref("/users") let snapshot = await dbRef.orderByChild("UID").equalTo(uid).once('value') if (snapshot.exists()){return snapshot} else {return false} } async function verifyExists(pid) { let productRef = database.ref("/products/"+pid) let snapshot = await productRef.once('value') if (snapshot.exists()) { return true } else{ return false } } async function verifyOwner(uid, pid) { let productRef = database.ref("/products/"+pid) let snapshot = await productRef.once('value') let item = snapshot.val() if (item.owner == uid || uid == "If84zSzRvlcCqRs0ZPJRpAcY1He2"){ return true } else { return false } } function sendEmail(address, subject, content){ var mailOptions = { from: 'Project GG', to: address, subject: subject, text: content } transporter.sendMail(mailOptions, function(error, info){ if (error) { console.log(error) } }) } app.get('*', function(request, responce){ responce.status(404).render('404.ejs') }) app.post('*', function(request, responce){ responce.status(404).send({success:false, error:"404"}) }) exports.application = functions.https.onRequest(app)