From b7dec6bfa2eede5a5a8f385a766a43e3604fb806 Mon Sep 17 00:00:00 2001 From: Max Hunt Date: Sat, 9 May 2020 21:23:58 +0100 Subject: [PATCH] Update --- functions/index.js | 186 ++++++++++++- functions/views/js/fAuth.js | 73 ++--- functions/views/js/fdb.js | 150 ++++++----- package-lock.json | 517 ++++++++++++++++++++++++++++++++++++ package.json | 1 + server.js | 193 +++++++++++++- 6 files changed, 981 insertions(+), 139 deletions(-) diff --git a/functions/index.js b/functions/index.js index 11ff9f1..9595aa4 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,21 +1,21 @@ const functions = require('firebase-functions'); -var express = require('express') -var logger = require('morgan') -var bodyParser = require('body-parser') -var admin = require("firebase-admin"); -var serviceAccount = require("./project-gg-3b754-firebase-adminsdk-4848h-5a5778b77b.json"); +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"); -var firebaseadmin = admin.initializeApp({ +let firebaseadmin = admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://project-gg-3b754.firebaseio.com" }) -var database = firebaseadmin.database() +let database = firebaseadmin.database() -var app = express() +let app = express() -app.use(bodyParser.json()) app.use(bodyParser.urlencoded({extended: true})) +app.use(bodyParser.json({ limit: '10mb' })); app.use(logger('dev')) app.use(express.static('views')) @@ -295,6 +295,174 @@ app.post('/ship-api', function(request, responce){ } }) +app.post('/login-user-api', function(request, responce){ + if (request.body.uToken && request.body.user) { + admin.auth().verifyIdToken(request.body.uToken) + .then(async function(decodedToken) { + let user = request.body.user + let uid = decodedToken.uid + + if (uid != user.uid){ + responce.send({success:false, error:'Stop hacking'}) + } + else { + let rsp = await checkNewUser(user) + responce.send(rsp) + } + }) + .catch(function(error) { + responce.send({success:false, error:'invalid auth token'}) + console.log(error) + }); + } + else { + responce.send({error: 'invalid data'}) + } +}) + +app.post('/shipping-adress-edit-api', function(request, responce){ + if (request.body.uToken && request.body.address) { + admin.auth().verifyIdToken(request.body.uToken) + .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({error: 'invalid data'}) + } +}) + +app.post('/new-product-api', function(request, responce){ + if (request.body.uToken && request.body.product && request.body.image) { + admin.auth().verifyIdToken(request.body.uToken) + .then(async function(decodedToken) { + let uid = decodedToken.uid + let image = request.body.image + let product = request.body.product + + let imageName = image.name + + let newProductRef = database.ref('/products') + let key = await newProductRef.push(product).then(key => { + let productKey = key.key + let imgPath = productKey + '/' + imageName + let productRef = database.ref('/products/' + productKey) + productRef.update({img: imgPath}).then(function(){ + responce.send({success:true, imgRef:'/product-img/'+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) + }) + + }) + .catch(function(error) { + responce.send({success:false, error:'invalid auth token'}) + console.log(error) + }); + } + else { + responce.send({error: 'invalid data'}) + } +}) + +app.post('/update-product-api', function(request, responce){ + if (request.body.uToken && request.body.product && request.body.productID) { + admin.auth().verifyIdToken(request.body.uToken) + .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'}) + } +}) + + +async function checkNewUser(user){ + let snapshot = await checkUserExists(user.uid) + if (snapshot){ + let users = snapshot.val() + var keys = Object.keys(users) + uData = users[keys[0]] + let retData = {success:true, userName:uData.fName + " " + uData.lName, address:uData.address} + return retData + } + else { + console.log("Creating new user") + let uData = { + fName:user.displayName, + lName:"", + UID:user.uid, + email:user.email, + address:"" + } + return await createNewUser(uData) + } +} + +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 createNewUser(uData){ + let userRef = database.ref('/users') + let x = await userRef.push(uData) + return {success:true, userName:uData.fName + " " + uData.lName, address:uData.address} +} async function authorisedToPurchase(uid, pid){ return true diff --git a/functions/views/js/fAuth.js b/functions/views/js/fAuth.js index 06ef4f7..86d57fe 100644 --- a/functions/views/js/fAuth.js +++ b/functions/views/js/fAuth.js @@ -2,19 +2,27 @@ function checkAuth(){ firebase.auth().onAuthStateChanged(function(user){ if (user) { document.getElementById('uname-dom').innerHTML = "Loading..." - let database = firebase.database() - var uid = user.uid - var dbRef = database.ref("/users") - dbRef.orderByChild("UID").equalTo(uid).once('value', function(snapshot){ - vals = snapshot.val() - var keys = Object.keys(vals) - uData = vals[keys[0]] - document.getElementById('uname-dom').innerHTML = "Hello, " + uData.fName - if (!uData.address) { - document.getElementsByClassName("notifications")[0].innerHTML = "🔔 | Update shipping address" - document.getElementsByClassName("notifications")[0].setAttribute("style", "color: red;") - } + firebase.auth().currentUser.getIdToken().then(function(idToken) { + let url = 'login-user-api' + let data = {uToken: idToken, user: user} + let postData = {method: 'POST', body: JSON.stringify(data),headers: {'Content-Type': 'application/json'}} + fetch(url, postData) + .then(response => response.json()) + .then(function(result){ + if (result.success == true) { + document.getElementById('uname-dom').innerHTML = "Hello, " + result.userName + if (!result.address) { + document.getElementsByClassName("notifications")[0].innerHTML = "🔔 | Update shipping address" + document.getElementsByClassName("notifications")[0].setAttribute("style", "color: red;") + } + } + else { + console.log(result.error) + document.getElementsByClassName("notifications")[0].innerHTML = "🔔 | What the fuck just happened....." + document.getElementsByClassName("notifications")[0].setAttribute("style", "color: pink;") + } + }) }) document.getElementById('uname-field').setAttribute("style", "display: block;") @@ -46,7 +54,6 @@ function signinwithgoogle(){ var googleAuthProvider = new firebase.auth.GoogleAuthProvider() firebase.auth().signInWithPopup(googleAuthProvider) .then(function(data){ - checkNewUser(data) console.log('User signed in...') }) .catch(function(error){ @@ -54,41 +61,10 @@ function signinwithgoogle(){ }) } -function checkNewUser(credential){ - let database = firebase.database() - var uid = credential.user.uid - var dbRef = database.ref("/users") - dbRef.orderByChild("UID").equalTo(uid).once('value', function(snapshot){ - if (snapshot.exists()){ - let uData = snapshot.val() - console.log(uData) - console.log("Logged in User: " + uData.fName + " " + uData.lName) - } - else { - console.log("Creating new user") - let uData = { - fName:credential.user.displayName, - lName:"", - UID:credential.user.uid, - email:credential.user.email, - address:"" - } - let itemRef = database.ref('/users') - itemRef.push(uData) - .then(function(){ - console.log("Added "+credential.displayName+" to user database") - window.location.replace('home') - }) - .catch(function(error){console.log(error)}) - } - }) -} - function signinwithfb(){ var fbAuthProvider = new firebase.auth.FacebookAuthProvider() firebase.auth().signInWithPopup(fbAuthProvider) .then(function(data){ - checkNewUser(data) console.log('User signed in...') }) .catch(function(error){ @@ -107,12 +83,9 @@ function signinwithemail(){ auth.signInWithEmailAndPassword(email, pass) .catch(e => console.log(e.message)) .then(function(data){ - checkNewUser(data) txtPassword.value = '' txtEmail.value = '' }) - - } function signout(){ @@ -125,7 +98,7 @@ function signout(){ var pwField = document.getElementById("fpwd"); pwField.addEventListener("keyup", function(event) { if (event.keyCode === 13) { - event.preventDefault(); - document.getElementById("blogin").click(); + event.preventDefault() + document.getElementById("blogin").click() } -}); +}) diff --git a/functions/views/js/fdb.js b/functions/views/js/fdb.js index 5beb5ba..b787854 100644 --- a/functions/views/js/fdb.js +++ b/functions/views/js/fdb.js @@ -1,14 +1,12 @@ -var permissionToLeavePage1 = false -var permissionToLeavePage2 = false +const toBase64 = file => new Promise((resolve, reject) => { + const reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = () => resolve(reader.result) + reader.onerror = error => reject(error) +}) -function leavePage(){ - if (permissionToLeavePage1 && permissionToLeavePage2) { - window.location.replace('home?itemAdded=true') - } -} - -function productSubmitEventHandler(){ - data = { +async function productSubmitEventHandler(){ + let newProduct = { id: 1, name: "", desc: "", @@ -29,35 +27,50 @@ function productSubmitEventHandler(){ const imgBtn = document.getElementById('pImg') - var sessUid = firebase.auth().currentUser.uid + let sessUid = firebase.auth().currentUser.uid - data.id = 999 - data.name = nameField.value - data.desc = descField.value - data.location = locField.value + newProduct.id = 999 + newProduct.name = nameField.value + newProduct.desc = descField.value + newProduct.location = locField.value if (stockField.value) { - data.stock = stockField.value + newProduct.stock = stockField.value } - data.price = priceField.value - data.owner = sessUid - data.holder = sessUid + newProduct.price = priceField.value + newProduct.owner = sessUid + newProduct.holder = sessUid - var productKey = addItem(data) - console.log(productKey) - - var image = imgBtn.files[0] - var imgPath = productKey + '/' + image.name - var storageRef = firebase.storage().ref('/product-img/' + imgPath) + let image = imgBtn.files[0] + imageName = image.name + // imageB64 = await toBase64(image) + let imagePackage = {name:imageName, b64:null} const submitBtn = document.getElementById('pSend') submitBtn.innerHTML = "Uploading..." submitBtn.disabled = true - updateDBImg(productKey, imgPath) - - storageRef.put(image).then(function(){ - permissionToLeavePage2 = true - leavePage() + firebase.auth().currentUser.getIdToken().then(function(idToken){ + let url = 'new-product-api' + let data = {uToken: idToken, product: newProduct, image: imagePackage} + let postData = {method: 'POST', body: JSON.stringify(data), headers: {'Content-Type': 'application/json'}} + fetch(url, postData) + .then(response => response.json()) + .then(function(result){ + if (result.success) { + let imageRef = firebase.storage().ref(result.imgRef) + imageRef.put(image).then(function(){ + window.location.replace('home?itemAdded=true') + }) + .catch(e=>{ + console.log(e) + submitBtn.innerHTML = "Error..." + }) + } + else { + submitBtn.innerHTML = "Error..." + console.log(result.error) + } + }) }) } @@ -80,19 +93,31 @@ function productUpdateEventHandler() { submitBtn.innerHTML = "Updating..." submitBtn.disabled = true - var database = firebase.database() - var productRef = database.ref("/products/"+item_id) - productRef.update({ + updates = { name: nameField.value, desc: descField.value, location: locField.value, stock: stockField.value, price: priceField.value - }) - .then(function(){ - submitBtn.setAttribute("style", "width: 300px; background: #00DD00;cursor: pointer;") - submitBtn.innerHTML = "Done!, Go Home..." - submitBtn.disabled = false + } + + firebase.auth().currentUser.getIdToken().then(function(idToken){ + let url = 'update-product-api' + let data = {uToken: idToken, product: updates, productID: item_id} + let postData = {method: 'POST', body: JSON.stringify(data), headers: {'Content-Type': 'application/json'}} + fetch(url, postData) + .then(response => response.json()) + .then(function(result){ + if (result.success) { + submitBtn.setAttribute("style", "width: 300px; background: #00DD00;cursor: pointer;") + submitBtn.innerHTML = "Done!, Go Home..." + submitBtn.disabled = false + } + else { + console.log(result.error) + submitBtn.innerHTML = "Error..." + } + }) }) } else { @@ -100,25 +125,6 @@ function productUpdateEventHandler() { } } -function addItem(item){ - var database = firebase.database() - var itemRef = database.ref('/products') - var key = itemRef.push(item) - return key.key -} - -function updateDBImg(key, value){ - console.log("Updating db, key=" + key + " value="+value+" total=" + '/products/' + key) - var database = firebase.database() - var itemRef = database.ref('/products/' + key) - console.log("itemRef") - console.log(itemRef) - itemRef.update({img: value}).then(function(){ - permissionToLeavePage1 = true - leavePage() - }) -} - function updateImgs() { const storage = firebase.storage() const rootReference = storage.ref('/product-img') @@ -290,21 +296,27 @@ function showShipField(){ } function addShippingAddress(){ - let database = firebase.database() - var usersRef = database.ref("/users") - usersRef.orderByChild("UID").equalTo(firebase.auth().currentUser.uid).once('value', function(snapshot){ - vals = snapshot.val() - var keys = Object.keys(vals) - userKey = keys[0] - userRef = database.ref("/users/"+userKey) - userRef.update({address:document.getElementById('shippingaddressinput').value}) - .then(function(){ - document.getElementById("shippingaddressinput").value = "" - document.getElementById("shippingaddressinput").placeholder = "Success!" + let newAddress = document.getElementById('shippingaddressinput').value + firebase.auth().currentUser.getIdToken().then(function(idToken){ + let url = 'shipping-adress-edit-api' + let data = {uToken: idToken, address: newAddress} + let postData = {method: 'POST', body: JSON.stringify(data),headers: {'Content-Type': 'application/json'}} + fetch(url, postData) + .then(response => response.json()) + .then(function(result){ + if (result.success) { + document.getElementById("shippingaddressinput").value = "" + document.getElementById("shippingaddressinput").placeholder = "Success!" + } + else { + document.getElementById("shippingaddressinput").value = "" + document.getElementById("shippingaddressinput").placeholder = "FAIL, " + esult.error + } }) - .catch(e => {console.log(e)}) }) } + + try { var addressField = document.getElementById("shippingaddressinput") addressField.addEventListener("keyup", function(event) { diff --git a/package-lock.json b/package-lock.json index fc743ef..cba405c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,16 +4,109 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@firebase/analytics": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.4.tgz", + "integrity": "sha512-x5Hxj3B9Zm4H6CEjMD/J86WjmiX9C6AhBBltaYzWMtqkqa/WvvWMicl4MpwZXjOdBbOd286oGgJPFqQMUYI/WQ==", + "requires": { + "@firebase/analytics-types": "0.3.0", + "@firebase/component": "0.1.11", + "@firebase/installations": "0.4.9", + "@firebase/logger": "0.2.3", + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/analytics-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.3.0.tgz", + "integrity": "sha512-0AJ6xn53Qn0D/YOVHHvlWFfnzzRSdd98Lr8Oqe1PJ2HPIN+o7qf03YmOG7fLpR1uplcWd+7vGKmxUrN3jKUBwg==" + }, + "@firebase/app": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.3.tgz", + "integrity": "sha512-59Q/XNi+QyV1GOvxN+BusoKjqDKUjDupePDhlT6SqvFdvb03TjG03fSfurhXGXmTk6f500aOIyVJ8UlYpTYrsg==", + "requires": { + "@firebase/app-types": "0.6.0", + "@firebase/component": "0.1.11", + "@firebase/logger": "0.2.3", + "@firebase/util": "0.2.46", + "dom-storage": "2.1.0", + "tslib": "1.11.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, "@firebase/app-types": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.0.tgz", "integrity": "sha512-ld6rzjXk/SUauHiQZJkeuSJpxIZ5wdnWuF5fWBFQNPaxsaJ9kyYg9GqEvwZ1z2e6JP5cU9gwRBlfW1WkGtGDYA==" }, + "@firebase/auth": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.5.tgz", + "integrity": "sha512-76ejEQrJ81s2ZI2RV/AoZnw3sDl7dZSpaJJtPlhqlahymtQ2sSeAZJAmECcTB27PF6EeCdRhB9qOIKGAEAhbJg==", + "requires": { + "@firebase/auth-types": "0.10.0" + } + }, "@firebase/auth-interop-types": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.4.tgz", "integrity": "sha512-CLKNS84KGAv5lRnHTQZFWoR11Ti7gIPFirDDXWek/fSU+TdYdnxJFR5XSD4OuGyzUYQ3Dq7aVj5teiRdyBl9hA==" }, + "@firebase/auth-types": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.0.tgz", + "integrity": "sha512-VuW7c+RAk3AYPU0Hxmun3RzXn7fbJDdjQbxvvpRMnQ9zrhk8mH42cY466M0n4e/UGQ+0smlx5BqZII8aYQ5XPg==" + }, "@firebase/component": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.10.tgz", @@ -45,11 +138,308 @@ "@firebase/app-types": "0.6.0" } }, + "@firebase/firestore": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.14.3.tgz", + "integrity": "sha512-vmkXa5Msumutf0ZQjF8AQQwXr4mXI7D8TBbI44w+CMQEnKcD5MW7Dr1SmCTWy8+kNAAFwdA6lCiUtDY5Gx/Hlw==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/firestore-types": "1.10.1", + "@firebase/logger": "0.2.3", + "@firebase/util": "0.2.46", + "@firebase/webchannel-wrapper": "0.2.40", + "@grpc/grpc-js": "0.8.1", + "@grpc/proto-loader": "^0.5.0", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + }, + "@grpc/grpc-js": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.8.1.tgz", + "integrity": "sha512-e8gSjRZnOUefsR3obOgxG9RtYW2Mw83hh7ogE2ByCdgRhoX0mdnJwBcZOami3E0l643KCTZvORFwfSEi48KFIQ==", + "requires": { + "semver": "^6.2.0" + } + } + } + }, + "@firebase/firestore-types": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.10.1.tgz", + "integrity": "sha512-vyKdm+AYUFT8XeUX62IOqaqPFCs/mAMoSEsqIz9HnSVsqCw/IocNjtjSa+3M80kRw4V8fI7JI+Xz6Wg5VJXLqA==" + }, + "@firebase/functions": { + "version": "0.4.43", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.43.tgz", + "integrity": "sha512-9cBGRr5JPcshtdUPpWuzsRIVPcWWNncK97QWBoFakVymPjvFNS3r0ZxD3hSUr9i05VrZdrqJfdljTNm8eEmJiA==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/functions-types": "0.3.16", + "@firebase/messaging-types": "0.4.4", + "isomorphic-fetch": "2.2.1", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/functions-types": { + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.3.16.tgz", + "integrity": "sha512-kHhBvSYiY2prY4vNQCALYs1+OruTdylvGemHG6G6Bs/rj3qw7ui3WysBsDU/rInJitHIcsZ35qrtanoJeQUIXQ==" + }, + "@firebase/installations": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.9.tgz", + "integrity": "sha512-5oY3iycidoK2MhNl4GiFYn/B9rbW69VLpH54EGEFl1UruGk464WyqC7RhJxYl8bUkFwZ4gg99MXMq/JhF0vcJA==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/installations-types": "0.3.3", + "@firebase/util": "0.2.46", + "idb": "3.0.2", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/installations-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.3.tgz", + "integrity": "sha512-XvWhPPAGeZlc+CfCA8jTt2pv19Jovi/nUV73u30QbjBbk5xci9bp5I29aBZukHsR6YNBjFCLSkLPbno4m/bLUg==" + }, "@firebase/logger": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.2.tgz", "integrity": "sha512-MbEy17Ha1w/DlLtvxG89ScQ+0+yoElGKJ1nUCQHHLjeMNsRwd2wnUPOVCsZvtBzQp8Z0GaFmD4a2iG2v91lEbA==" }, + "@firebase/messaging": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.15.tgz", + "integrity": "sha512-WswV3JtxAgqc0LPQtIBdMWJdMhVZu7gKF6MO5ETIpNaLZZ0QayYNu5+G9btoZz218HB/gvUp2NFX43OWAsqdZw==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/installations": "0.4.9", + "@firebase/messaging-types": "0.4.4", + "@firebase/util": "0.2.46", + "idb": "3.0.2", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/messaging-types": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.4.4.tgz", + "integrity": "sha512-JGtkr+1A1Dw7+yCqQigqBfGKtq0gTCruFScBD4MVjqZHiqGIYpnQisWnpGbkzPR6aOt6iQxgwxUhHG1ulUQGeg==" + }, + "@firebase/performance": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.3.tgz", + "integrity": "sha512-YcoMnJWnlSQwi+eL1BDLWK7/sMlFoT7+TSJjN/C5loOZ3HWLATziGzevQSZkpajyXZ8nOylVhEGHABLHM0qqNA==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/installations": "0.4.9", + "@firebase/logger": "0.2.3", + "@firebase/performance-types": "0.0.12", + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/performance-types": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.12.tgz", + "integrity": "sha512-eIDF7CHetOE5sc+hCaUebEn/2Aiaju7UkgZDTl7lNQHz5fK9wJ/11HaE8WdnDr//ngS3lQAGC2RB4lAZeEWraA==" + }, + "@firebase/polyfill": { + "version": "0.3.35", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.35.tgz", + "integrity": "sha512-O04KLyrHFXnA8Xsx+zEBlHu6iHWWhXNtOIE9WhWZO+D9onVjNEY3l7KtXvwpH/b+R1PE0Uyxy0cSGK9f5el6HQ==", + "requires": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } + }, + "@firebase/remote-config": { + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.20.tgz", + "integrity": "sha512-7ib4YhhQ/yjEhMiFsYEt4lId+9mzv5CGhGccArmgCyTNSkeImS/BqAeqcOtveyFXHSv9RDHaA4/L6066LsudRQ==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/installations": "0.4.9", + "@firebase/logger": "0.2.3", + "@firebase/remote-config-types": "0.1.8", + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/remote-config-types": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.8.tgz", + "integrity": "sha512-K12IBHO7OD4gCW0FEqZL9zMqVAfS4+joC4YIn3bHezZfu3RL+Bw1wCb0cAD7RfDPcQxWJjxOHpce4YhuqSxPFA==" + }, + "@firebase/storage": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.33.tgz", + "integrity": "sha512-pFhsy+LglBjyVAYd6LlyUTeHTXR4yV24eL+fLZCYOE3W23Ago/3RpkX+MaEP5ZSpdFmnV/H6R6qDClSFx1EEYA==", + "requires": { + "@firebase/component": "0.1.11", + "@firebase/storage-types": "0.3.11", + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, + "@firebase/storage-types": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.3.11.tgz", + "integrity": "sha512-EMOo5aeiJIa8eQ/VqjIa/DYlDcEJX1V84FOxmLfNWZIlmCSvcqx9E9mcNlOnoUB4iePqQjTMQRtKlIBvvEVhVg==" + }, "@firebase/util": { "version": "0.2.45", "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.45.tgz", @@ -58,6 +448,11 @@ "tslib": "1.11.1" } }, + "@firebase/webchannel-wrapper": { + "version": "0.2.40", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.40.tgz", + "integrity": "sha512-f0jc79nQvwcwhOGFAD9b5K55Cb/a0A7LKBdRyQgVFLBGm+MuSFF5Rm/5Ll8/u72hJhbdICQj+xYl2uIuCMdXFQ==" + }, "@google-cloud/common": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.4.0.tgz", @@ -1036,6 +1431,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1299,6 +1699,11 @@ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=" }, + "dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==" + }, "dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", @@ -1421,6 +1826,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1770,6 +2183,65 @@ "unpipe": "~1.0.0" } }, + "firebase": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.14.3.tgz", + "integrity": "sha512-qExwE/vhf/l6Mf8ES3IFX1SB6/DysKPtvrIWnIuswmRMeSA9eERwrqp4Pom4NHhzjBP1jOmlIPKeOplsNwMlOQ==", + "requires": { + "@firebase/analytics": "0.3.4", + "@firebase/app": "0.6.3", + "@firebase/app-types": "0.6.0", + "@firebase/auth": "0.14.5", + "@firebase/database": "0.6.2", + "@firebase/firestore": "1.14.3", + "@firebase/functions": "0.4.43", + "@firebase/installations": "0.4.9", + "@firebase/messaging": "0.6.15", + "@firebase/performance": "0.3.3", + "@firebase/polyfill": "0.3.35", + "@firebase/remote-config": "0.1.20", + "@firebase/storage": "0.3.33", + "@firebase/util": "0.2.46" + }, + "dependencies": { + "@firebase/component": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.11.tgz", + "integrity": "sha512-HZ0fwtv8/b3KV4NUOqlcIr03+CpBKW0F1Jo6/HJ39AutS6XXbM2jtpXOd1wMq9lbhBHgEwt1sMPNKoPR1bFflQ==", + "requires": { + "@firebase/util": "0.2.46", + "tslib": "1.11.1" + } + }, + "@firebase/database": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.2.tgz", + "integrity": "sha512-0D0WOqYlNg3NMi0hJPx18tun6FMfr31d1dZB0Lai0K5jScBhPr2h4Fy7yp5lyOklwDSAoBYxmpX4nzHuDheL9Q==", + "requires": { + "@firebase/auth-interop-types": "0.1.4", + "@firebase/component": "0.1.11", + "@firebase/database-types": "0.5.0", + "@firebase/logger": "0.2.3", + "@firebase/util": "0.2.46", + "faye-websocket": "0.11.3", + "tslib": "1.11.1" + } + }, + "@firebase/logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.3.tgz", + "integrity": "sha512-PrYcr1bWF+QpVnFxvNSZYBAzgL1WJFWIOvoLAfvRoXiinwqh1jbePN6lXbX7c8THaNUelEYIUOzDPdJ4IZ5+Sw==" + }, + "@firebase/util": { + "version": "0.2.46", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.46.tgz", + "integrity": "sha512-rKzQRc7YAbve+MECliis5ac6lRB1AZgOyZdoAbXaEtmGWUwnlM99uNhCekA963CaBkzlHwQG2inLf3WGW7nLFA==", + "requires": { + "tslib": "1.11.1" + } + } + } + }, "firebase-admin": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-8.11.0.tgz", @@ -2454,6 +2926,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -2742,6 +3219,31 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + } + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -3607,6 +4109,11 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, + "promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, "protobufjs": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz", @@ -4791,6 +5298,11 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4935,6 +5447,11 @@ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 2489acd..37dbc78 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "body-parser": "^1.19.0", "ejs": "^3.1.2", "express": "^4.17.1", + "firebase": "^7.14.3", "firebase-admin": "^8.11.0", "firebase-tools": "^8.2.0", "morgan": "^1.10.0", diff --git a/server.js b/server.js index dc2a194..d148787 100644 --- a/server.js +++ b/server.js @@ -1,19 +1,19 @@ -var express = require('express') -var logger = require('morgan') -var bodyParser = require('body-parser') -var admin = require("firebase-admin"); -var serviceAccount = require("./secrets/project-gg-3b754-firebase-adminsdk-4848h-5a5778b77b.json"); +let express = require('express') +let logger = require('morgan') +let bodyParser = require('body-parser') +let admin = require("firebase-admin"); +let serviceAccount = require("./secrets/project-gg-3b754-firebase-adminsdk-4848h-5a5778b77b.json"); -var firebaseadmin = admin.initializeApp({ +let firebaseadmin = admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://project-gg-3b754.firebaseio.com" }) -var database = firebaseadmin.database() -var auth = admin.auth(); +let database = firebaseadmin.database() +let auth = admin.auth(); -var app = express() -app.use(bodyParser.json()) +let app = express() app.use(bodyParser.urlencoded({extended: true})) +app.use(bodyParser.json({ limit: '10mb' })); app.use(logger('dev')) app.use(express.static('views')) @@ -301,6 +301,143 @@ app.post('/ship-api', function(request, responce){ } }) +app.post('/login-user-api', function(request, responce){ + if (request.body.uToken && request.body.user) { + admin.auth().verifyIdToken(request.body.uToken) + .then(async function(decodedToken) { + let user = request.body.user + let uid = decodedToken.uid + + if (uid != user.uid){ + responce.send({success:false, error:'Stop hacking'}) + } + else { + let rsp = await checkNewUser(user) + responce.send(rsp) + } + }) + .catch(function(error) { + responce.send({success:false, error:'invalid auth token'}) + console.log(error) + }); + } + else { + responce.send({error: 'invalid data'}) + } +}) + +app.post('/shipping-adress-edit-api', function(request, responce){ + if (request.body.uToken && request.body.address) { + admin.auth().verifyIdToken(request.body.uToken) + .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({error: 'invalid data'}) + } +}) + +app.post('/new-product-api', function(request, responce){ + if (request.body.uToken && request.body.product && request.body.image) { + admin.auth().verifyIdToken(request.body.uToken) + .then(async function(decodedToken) { + let uid = decodedToken.uid + let image = request.body.image + let product = request.body.product + + let imageName = image.name + + let newProductRef = database.ref('/products') + let key = await newProductRef.push(product).then(key => { + let productKey = key.key + let imgPath = productKey + '/' + imageName + let productRef = database.ref('/products/' + productKey) + productRef.update({img: imgPath}).then(function(){ + responce.send({success:true, imgRef:'/product-img/'+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) + }) + + }) + .catch(function(error) { + responce.send({success:false, error:'invalid auth token'}) + console.log(error) + }); + } + else { + responce.send({error: 'invalid data'}) + } +}) + +app.post('/update-product-api', function(request, responce){ + if (request.body.uToken && request.body.product && request.body.productID) { + admin.auth().verifyIdToken(request.body.uToken) + .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'}) + } +}) + + + + + app.post('/demo-api', function(request, responce){ if (request.body.item && request.body.user) { @@ -324,11 +461,45 @@ app.post('/demo-api', function(request, responce){ }); } else { - responce.send({error: 'invalid data'}) + responce.send({success:false, error: 'invalid data'}) } }) +async function checkNewUser(user){ + let snapshot = await checkUserExists(user.uid) + if (snapshot){ + let users = snapshot.val() + var keys = Object.keys(users) + uData = users[keys[0]] + let retData = {success:true, userName:uData.fName + " " + uData.lName, address:uData.address} + return retData + } + else { + console.log("Creating new user") + let uData = { + fName:user.displayName, + lName:"", + UID:user.uid, + email:user.email, + address:"" + } + return await createNewUser(uData) + } +} + +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 createNewUser(uData){ + let userRef = database.ref('/users') + let x = await userRef.push(uData) + return {success:true, userName:uData.fName + " " + uData.lName, address:uData.address} +} async function authorisedToPurchase(uid, pid){