Bad request while deploying cloud function in firebase. HTTP Error: 400 - node.js

I'm trying to deploy cloud function to create push notification (chat messaging) on firebase (Firestore).
But when i'm trying to do this - i'm always getting HTTP Error: 400, The request has errors.
Looks like path of collections is good.
exports.notifyNewMessage = functions.firestore
.document('/chat/{toUserId}/chatRoom/{fromUserId}/chatItems')
.onCreate((docSnapshot, context) => {
const message = docSnapshot.data();
const recipientId = context.params.toUserId; // получатель сообщения
const senderId = context.params.fromUserId; // отправитель сообщения
const senderName = message['username'];
if (recipientId === senderId) {
} else {
return admin.forestore().doc('tokens/' + recipientId).get().then(userDoc => {
const tokens = userDoc.get('tokens')
const notificationBody = (message['type'] === "TEXT") ? message['textMessage'] : "New message with Image"
const payload = {
notification: {
title: senderName + " sent you a message",
body: notificationBody,
clickAction: "ChatActivity" // возможно, это только для андроида
},
data: {
USER_NAME: senderName,
USER_ID: message['senderId']
}
}
return admin.messaging().sendToDevice(tokens, payload).then( response => {
const stillRegisteredTokens = tokens
response.results.forEach((result, index) => {
const error = result.error
if (error) {
const failedRegistrationToken = tokens[index]
console.error('failed token', failedRegistrationToken, error)
if (error.code === 'messaging/invalid-registration-token' || error.code == 'messaging/registration-token-not-registred') {
const failedIndex = stillRegisteredTokens.indexOf(failedRegistrationToken)
if (failedIndex > -1) {
stillRegisteredTokens.splice(failedIndex, 1)
}
}
}
})
return admin.firestore().doc("tokens" + recipientId).update({
tokens: stillRegisteredTokens
})
})
})
}
})
also i would ask about line "clickAction: "ChatActivity" it only for android? how can i do same to ios?
Thx a lot!

Try to delete the function from firebase console and redeploy
or
try changing Internet Service Provider and deploy

Related

firebase admin.auth().getUserByProviderUid is not a function

I want to delete by facebook provider user in my firebase authentication using this question in my nodeJs. But somehow i getting error that getUserByProviderUid is not a function. I attached the error message below.
Here is code
exports.deleteUserData = functions.https.onRequest(async (req,
res) => {
try {
const signedRequest = req.body.signed_request;
console.log('signRewues',signedRequest)
const userObj = parseSignedRequest(signedRequest,
'Facebook secret');
console.log('User Obj',userObj, userObj.user_id);
const userRecord = await
admin.auth().getUserByProviderUid("facebook.com",
userObj.user_id);
console.log('userRecord',userRecord);
await admin.auth().deleteUser(userRecord.uid);
res.json({
url: "<URL>",
confirmation_code: "<Code>",
});
} catch (e) {
console.log(e);
res.status(400).json({
message: "Bad Request",
});
}
});
function base64decode(data) {
while (data.length % 4 !== 0) {
data += "=";
}
data = data.replace(/-/g, "+").replace(/_/g, "/");
return Buffer.from(data, "base64").toString("utf-8");
};
function parseSignedRequest(signedRequest, secret) {
var encoded_data = signedRequest.split(".", 2);
// decode the data
var sig = encoded_data[0];
var json = base64decode(encoded_data[1]);
var data = JSON.parse(json);
if (!data.algorithm || data.algorithm.toUpperCase() != "HMAC-
SHA256") {
throw Error(
"Unknown algorithm: " + data.algorithm + ". Expected HMAC-
SHA256"
);
}
var expected_sig = crypto
.createHmac("sha256", secret)
.update(encoded_data[1])
.digest("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace("=", "");
if (sig !== expected_sig) {
throw Error("Invalid signature: " + sig + ". Expected " +
expected_sig);
}
return data;
}
The getUserByProviderUid() was added in version 9.5.0 of Admin SDK. You'll have to update the Admin SDK to use it. Try upgrading to latest version.
npm i firebase-admin#latest

Firebase - Error: There was an error deploying functions

Ok, y'all I am in a pickle here. I've been working on all my firebase functions for a few days and thought I was making really good progress until I went to deploy after several days of testing with the firebase server and postman... It won't deploy T_T
The error I am getting in the terminal when I use firebase --debug deploy is:
2022-01-25T17:23:50.575Z] Total Function Deployment time: 57866
[2022-01-25T17:23:50.575Z] 1 Functions Deployed
[2022-01-25T17:23:50.575Z] 1 Functions Errored
[2022-01-25T17:23:50.575Z] 0 Function Deployments Aborted
[2022-01-25T17:23:50.575Z] Average Function Deployment time: 57864
Functions deploy had errors with the following functions:
api(us-central1)
[2022-01-25T17:23:50.713Z] Missing URI for HTTPS function in printTriggerUrls. This shouldn't happen
in functions: cleaning up build files...
[2022-01-25T17:23:50.719Z] >>> [apiv2][query] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api [none]
[2022-01-25T17:23:50.722Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list [none]
[2022-01-25T17:23:50.918Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list 200
[2022-01-25T17:23:50.918Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/tags/list {"child":["5fbdb989-6e6d-42bc-9a25-3073c3098d76"],"manifest":{},"name":"lxai-mentor-matching/gcf/us-central1","tags":[]}
[2022-01-25T17:23:50.918Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list [none]
[2022-01-25T17:23:50.931Z] <<< [apiv2][status] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api 404
[2022-01-25T17:23:50.933Z] <<< [apiv2][body] DELETE https://artifactregistry.googleapis.com/v1beta2/projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts/packages/api {"error":{"code":404,"message":"Repository does not exist: \"projects/lxai-mentor-matching/locations/us-central1/repositories/gcf-artifacts\"","status":"NOT_FOUND"}}
[2022-01-25T17:23:51.061Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list 200
[2022-01-25T17:23:51.063Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/tags/list {"child":["cache"],"manifest":{"sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6":{"imageSizeBytes":"421918451","layerId":"","mediaType":"application/vnd.docker.distribution.manifest.v2+json","tag":["api_version-15","latest"],"timeCreatedMs":"315532801000","timeUploadedMs":"1643131418106"}},"name":"lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76","tags":["api_version-15","latest"]}
[2022-01-25T17:23:51.064Z] >>> [apiv2][query] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list [none]
[2022-01-25T17:23:51.069Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 [none]
[2022-01-25T17:23:51.230Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/latest 202
[2022-01-25T17:23:51.231Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/latest {"errors":[]}
[2022-01-25T17:23:51.250Z] <<< [apiv2][status] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list 200
[2022-01-25T17:23:51.250Z] <<< [apiv2][body] GET https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/tags/list {"child":[],"manifest":{"sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f":{"imageSizeBytes":"13412478","layerId":"","mediaType":"application/vnd.docker.distribution.manifest.v2+json","tag":["latest"],"timeCreatedMs":"315532801000","timeUploadedMs":"1643131418618"}},"name":"lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache","tags":["latest"]}
[2022-01-25T17:23:51.251Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest [none]
[2022-01-25T17:23:51.256Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 202
[2022-01-25T17:23:51.256Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/api_version-15 {"errors":[]}
[2022-01-25T17:23:51.257Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 [none]
[2022-01-25T17:23:51.386Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest 202
[2022-01-25T17:23:51.386Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/latest {"errors":[]}
[2022-01-25T17:23:51.387Z] >>> [apiv2][query] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f [none]
[2022-01-25T17:23:51.683Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 202
[2022-01-25T17:23:51.683Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/manifests/sha256:efea96d0dec08db58767f472cc16a3c17c277e41d844a61bbdb745e49c7cd8e6 {"errors":[]}
[2022-01-25T17:23:51.728Z] <<< [apiv2][status] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f 202
[2022-01-25T17:23:51.729Z] <<< [apiv2][body] DELETE https://us.gcr.io/v2/lxai-mentor-matching/gcf/us-central1/5fbdb989-6e6d-42bc-9a25-3073c3098d76/cache/manifests/sha256:75f8940b6524c90f2b653b387e0cab4a9ae9f3dbebb2e5f4dfb03fc3345ead6f {"errors":[]}
[2022-01-25T17:23:51.852Z] Error: Failed to update function api in region us-central1
at /Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:38:11
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Fabricator.updateV1Function (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:255:32)
at async Fabricator.updateEndpoint (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:136:13)
at async handle (/Users/tmac/.nvm/versions/node/v17.3.0/lib/node_modules/firebase-tools/lib/deploy/functions/release/fabricator.js:75:17)
Error: There was an error deploying functions
Having read a few other posts here I am super confused as to what the error is and where I can hunt it down. Everything has been working locally with firebase serve. When I check the log files I get this:
11:23:52.550 AM
api
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":
{"code":3,"message":"Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation."},"authenticationInfo":{"principalEmail":"timmcmackenjr#gmail.com"},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","resourceName":"projects/lxai-mentor-matching/locations/us-central1/functions/api"}
One post here was about space in a file name, but that's not my issue, another was about package.json so I'm posting mine here but not sure what I am looking for. Any idea on how to dig deeper or what to look for so I can get deploy working again?
package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "16"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1"
},
"devDependencies": {
"firebase-functions-test": "^0.2.0"
},
"private": true
}
index.js
const functions = require('firebase-functions');
const app = require('express')();
const { postOneScream } = require('./handlers/screams');
const {
signup,
login,
uploadImage,
addUserDetails,
} = require('./handlers/users');
const { addMentee, getMentees, updateMentee } = require('./handlers/mentees');
const { addMentor, getMentors, updateMentor } = require('./handlers/mentors');
const { FBAuth } = require('./util/fbAuth');
//**POST ROUTES**
// Scream routes - Testing post functionality for social media feed posts
app.post('/screams', FBAuth, postOneScream);
// Signup route
app.post('/signup', signup);
// Sign In route
app.post('/login', login);
// Upload an image route
app.post('/users/image', FBAuth, uploadImage);
// Add details to user profile
app.post('/users', FBAuth, addUserDetails);
// Mentee Signup / Update
app.post('/mentees', FBAuth, addMentee);
app.post('/mentees', FBAuth, updateMentee);
// Mentor Signup
app.post('/mentors', FBAuth, addMentor);
app.post('/mentors', FBAuth, updateMentor);
//**GET ROUTES**
// Get all mentees
app.get('/mentees', getMentees);
// Get all mentors
app.get('/mentors', getMentors);
//**Export API**
// export api allows us to use express for our function formating
exports.api = functions.https.onRequest(app);
users.js
const { admin, db } = require('../util/admin');
const firebase = require('firebase');
const config = require('../util/config');
firebase.initializeApp(config);
const {
validateSignupData,
validateLoginData,
reduceUserDetails,
} = require('../util/validators');
exports.signup = async (req, res) => {
const newUser = {
email: req.body.email,
password: req.body.password,
confirmPassword: req.body.confirmPassword,
handle: req.body.handle,
};
// Validating the fields for user signup
const { valid, errors } = validateSignupData(newUser);
if (!valid) return res.status(400).json(errors);
const noImg = 'no-img.png';
const userDoc = await db.doc(`/users/${newUser.handle}`).get();
if (userDoc.exists) {
return res.status(400).json({ handle: 'This handle already taken' });
} else {
// Create user
let userId;
await firebase
.auth()
.createUserWithEmailAndPassword(newUser.email, newUser.password)
.then((data) => {
userId = data.user.uid;
return data.user.getIdToken();
})
.then((userToken) => {
// Add User to Users Collection
const uToken = userToken;
const userCredentials = {
handle: newUser.handle,
email: newUser.email,
createdAt: new Date().toISOString(),
imgURL: `https://firebasetorage.googleapis.com/v0/b/${config.storageBucket}/o/${noImg}?alt=media`,
userId,
};
db.doc(`/users/${newUser.handle}`).set(userCredentials);
return userToken;
})
.then((userToken) => {
return res
.status(201)
.json({ message: 'User created successfully', token: userToken });
})
.catch((err) => {
console.error(err);
if (err.code === 'auth/email-already-in-use') {
return res.status(400).json({ email: 'Email is already in use' });
} else {
return res.status(500).json({ error: err.code });
}
});
}
};
exports.login = (req, res) => {
const user = {
email: req.body.email,
password: req.body.password,
};
// Validating the fields for user login
const { valid, errors } = validateLoginData(user);
if (!valid) return res.status(400).json(errors);
// Log the user in and get a token
firebase
.auth()
.signInWithEmailAndPassword(user.email, user.password)
.then((data) => {
return data.user.getIdToken();
})
.then((token) => {
res.json({ token });
})
.catch((err) => {
console.error(err);
if (err.code === 'auth/wrong-password') {
return res.status(403).json({ general: 'Wrong credentials' });
} else {
return res.status(500).json({ error: err.code });
}
});
};
// Upload an image for user profile page
exports.uploadImage = (req, res) => {
const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');
const busboy = BusBoy({ headers: req.headers });
let imageFileName;
let imageToBeUploaded = {};
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
if (
mimetype !== 'image/jpeg' &&
mimetype !== 'image/png' &&
mimetype !== 'image/jpg'
) {
return res
.status(400)
.json({ error: 'Wrong file type, please use JPG/JPEG/PNG' });
}
const fileName = filename.filename + '';
const imageExtention = fileName.split('.')[fileName.split('.').length - 1];
// Not sure why we need to change file name but this is the tutorial recommendation
imageFileName = `${Math.round(
Math.random() * 10000000000,
)}.${imageExtention}`;
console.log(imageFileName);
const filePath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filePath, mimetype };
file.pipe(fs.createWriteStream(filePath));
});
busboy.on('finish', () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filePath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype,
},
},
})
.then(() => {
const imgURL = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`;
return db.doc(`/users/${req.user.handle}`).update({ imgURL });
})
.then(() => {
return res.json({ message: 'Image uploaded successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
});
busboy.end(req.rawBody);
};
// Add user details to user collection in db / user profile in react
exports.addUserDetails = (req, res) => {
let userDetails = reduceUserDetails(req.body);
db.doc(`/users/${req.user.handle}`)
.update(userDetails)
.then(() => {
return res.status(200).json({ message: 'Details added successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
screams.js
const { db } = require('../util/admin');
exports.postOneScream = (req, res) => {
const newScream = {
body: req.body.body,
userHandle: req.user.handle,
createdAt: new Date().toISOString(),
};
db.collection('screams')
.add(newScream)
.then((doc) => {
res.json({ message: `document ${doc.id} created successfully` });
})
.catch((err) => {
res.status(500).json({ error: 'something went wrong' });
console.error(err);
});
};
mentees.js
const { db } = require('../util/admin');
const { reduceMenteeDetails } = require('../util/validators');
// Add a mentee to the mentees collection
exports.addMentee = (req, res) => {
let menteeDetails = reduceMenteeDetails(req);
db.doc(`/mentees/${req.user.handle}`).set(menteeDetails)
.then(() => {
return res.status(200).json({ message: 'Details added successfully' });
}).catch(err => {
console.error(err);
return res.status(500).json({ error: err.code });
})
}
// Get all Mentees from the mentee collection
exports.getMentees = (req, res) => {
db.collection('mentees').get()
.then((data) => {
let mentees = [];
data.forEach((doc) => {
mentees.push(doc.data())
});
return res.json(mentees);
})
.catch(err => {
console.error(err);
return res.status(500).json({ error: err.code })
})
}
// Update an existing mentee
exports.updateMentee = (req, res) => {
let menteeDetails = reduceMenteeDetails(req);
db.doc(`/mentees/${req.user.handle}`).update(menteeDetails)
.then(() => {
return res.status(200).json({ message: 'Details added successfully' });
}).catch(err => {
console.error(err);
return res.status(500).json({ error: err.code });
})
}
mentors.js
const { db } = require('../util/admin');
const { reduceMentorDetails } = require('../util/validators');
// Add a mentor to the mentors collection
exports.addMentor = (req, res) => {
let mentorDetails = reduceMentorDetails(req);
db.doc(`/mentors/${req.user.handle}`)
.set(mentorDetails)
.then(() => {
return res.status(200).json({ message: 'Details added successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
// Get all mentors from the mentor collection
exports.getMentors = (req, res) => {
db.collection('mentors')
.get()
.then((data) => {
let mentors = [];
data.forEach((doc) => {
mentors.push(doc.data());
});
return res.json(mentors);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
// Update an existing mentor
exports.updateMentor = (req, res) => {
let mentorDetails = reduceMentorDetails(req);
db.doc(`/mentors/${req.user.handle}`)
.update(mentorDetails)
.then(() => {
return res.status(200).json({ message: 'Details added successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
validators.js
// Helper functions for validation of signup form
// Check if a field is empty
const isEmpty = (string) => {
if (string.trim() === '') return true;
else return false;
};
// Check if an email is valid in format
const isEmail = (email) => {
const regEx =
/^(([^<>()[\]\.,;:\s#\"]+(\.[^<>()[\]\.,;:\s#\"]+)*)|(\".+\"))#(([^<>()[\]\.,;:\s#\"]+\.)+[^<>()[\]\.,;:\s#\"]{2,})$/i;
if (email.match(regEx)) return true;
else return false;
};
//Validate signup credential entered
exports.validateSignupData = (data) => {
let errors = {};
if (isEmpty(data.email)) {
errors.email = 'Must not be empty';
} else if (!isEmail(data.email)) {
errors.email = 'Must be a valid email';
}
if (isEmpty(data.password)) errors.password = 'Must not be empty';
if (data.password !== data.confirmPassword)
errors.confirmPassword = 'Passwords do not match';
if (isEmpty(data.handle)) errors.handle = 'Must not be empty';
return {
errors,
valid: Object.keys(errors).length === 0 ? true : false,
};
};
// Validate Login Credentials entered
exports.validateLoginData = (data) => {
let errors = {};
if (isEmpty(data.email)) errors.email = 'Must not be empty';
if (isEmpty(data.password)) errors.password = 'Must not be empty';
return {
errors,
valid: Object.keys(errors).length === 0 ? true : false,
};
};
// User Details Updater - Checks for non-answers/blanks and return dict
exports.reduceUserDetails = (data) => {
let userDetails = {};
if (!isEmpty(data.fullName.trim())) userDetails.fullName = data.fullName;
if (!isEmpty(data.jobTitle.trim())) userDetails.jobTitle = data.jobTitle;
if (!isEmpty(data.affiliation.trim()))
userDetails.affiliation = data.affiliation;
if (!isEmpty(data.homeLocation.trim()))
userDetails.homeLocation = data.homeLocation;
if (!isEmpty(data.isLatinX.trim())) userDetails.isLatinX = data.isLatinX;
if (!isEmpty(data.bio.trim())) userDetails.bio = data.bio;
if (!isEmpty(data.website.trim())) {
// If user doesn't include the http://
if (data.website.trim().substring(0, 4) !== 'http') {
userDetails.website = `http://${data.website.trim()}`;
} else userDetails.website = data.website;
}
if (!isEmpty(data.publicProfile.trim()))
userDetails.publicProfile = data.publicProfile;
return userDetails;
};
// Mentee Details Updater - Checks for non-answers/blanks and return dict
exports.reduceMenteeDetails = (data) => {
const answers = data.body;
let menteeDetails = {};
// Things we can pull from the data.user or just geneate
menteeDetails.createdAt = new Date().toISOString();
menteeDetails.userId = data.user.uid;
menteeDetails.email = data.user.email;
menteeDetails.handle = data.user.handle;
//Things we can pull from the user's info in the user collection
menteeDetails.fullName = answers.fullName;
menteeDetails.isLatinX = answers.isLatinX;
menteeDetails.currentLocation = answers.currentLocation;
// Questions we need to ask in the mentee sign up flow
if (!isEmpty(answers.gender.trim())) menteeDetails.gender = answers.gender;
if (!isEmpty(answers.countryOrigin.trim()))
menteeDetails.countryOrigin = answers.countryOrigin;
if (!isEmpty(answers.affiliation.trim()))
menteeDetails.affiliation = answers.affiliation;
if (!isEmpty(answers.position.trim()))
menteeDetails.position = answers.position;
if (!isEmpty(answers.scholarOrWebsite.trim())) {
// If user doesn't include the http://
if (answers.scholarOrWebsite.trim().substring(0, 4) !== 'http') {
menteeDetails.scholarOrWebsite = `http://${answers.scholarOrWebsite.trim()}`;
} else menteeDetails.scholarOrWebsite = answers.scholarOrWebsite;
}
if (answers.languages.length > 0) menteeDetails.languages = answers.languages;
if (!isEmpty(answers.timezone.trim()))
menteeDetails.timezone = answers.timezone;
if (answers.mentorshipArea.length > 0)
menteeDetails.mentorshipArea = answers.mentorshipArea;
if (!isEmpty(answers.motivationStatement.trim()))
menteeDetails.motivationStatement = answers.motivationStatement;
if (answers.prefferedOutcomes.length > 0)
menteeDetails.prefferedOutcomes = answers.prefferedOutcomes;
if (!isEmpty(answers.discussAfter.trim()))
menteeDetails.discussAfter = answers.discussAfter;
if (!isEmpty(answers.careerGoals.trim()))
menteeDetails.careerGoals = answers.careerGoals;
if (answers.skillMentorship.length > 0)
menteeDetails.skillMentorship = answers.skillMentorship;
if (answers.researchAreas.length > 0)
menteeDetails.researchAreas = answers.researchAreas;
if (answers.careerAdvice.length > 0)
menteeDetails.careerAdvice = answers.careerAdvice;
if (!isEmpty(answers.workshopReviewer))
menteeDetails.workshopReviewer = answers.workshopReviewer;
if (!isEmpty(answers.peerReviewedPubs.trim()))
menteeDetails.peerReviewedPubs = answers.peerReviewedPubs;
if (!isEmpty(answers.topTierReviewer.trim()))
menteeDetails.topTierReviewer = answers.topTierReviewer;
if (!isEmpty(answers.topTierPub.trim()))
menteeDetails.topTierPub = answers.topTierPub;
if (!isEmpty(answers.highImpactReviewer.trim()))
menteeDetails.highImpactReviewer = answers.highImpactReviewer;
if (answers.conferencePreference.length > 0)
menteeDetails.conferencePreference = answers.conferencePreference;
if (!isEmpty(answers.otherConferences.trim())) {
let conferences = answers.otherConferences.split(',');
menteeDetails.conferencePreference =
menteeDetails.conferencePreference.concat(conferences);
}
if (!isEmpty(answers.peerReviewedHighImpact))
menteeDetails.peerReviewedHighImpact = answers.peerReviewedHighImpact;
return menteeDetails;
};
// Mentee Details Updater - Checks for non-answers/blanks and return dict
exports.reduceMentorDetails = (data) => {
const answers = data.body;
let mentorDetails = {};
// Things we can pull from the data.user or just geneate
mentorDetails.createdAt = new Date().toISOString();
mentorDetails.userId = data.user.uid;
mentorDetails.email = data.user.email;
mentorDetails.handle = data.user.handle;
//Things we can pull from the user's info in the user collection
mentorDetails.fullName = answers.fullName;
mentorDetails.isLatinX = answers.isLatinX;
mentorDetails.currentLocation = answers.currentLocation;
// Questions we need to ask in the mentor sign up flow
if (!isEmpty(answers.gender.trim())) mentorDetails.gender = answers.gender;
if (!isEmpty(answers.countryOrigin.trim()))
mentorDetails.countryOrigin = answers.countryOrigin;
if (!isEmpty(answers.affiliation.trim()))
mentorDetails.affiliation = answers.affiliation;
if (!isEmpty(answers.position.trim()))
mentorDetails.position = answers.position;
if (!isEmpty(answers.scholarOrWebsite.trim())) {
// If user doesn't include the http://
if (answers.scholarOrWebsite.trim().substring(0, 4) !== 'http') {
mentorDetails.scholarOrWebsite = `http://${answers.scholarOrWebsite.trim()}`;
} else mentorDetails.scholarOrWebsite = answers.scholarOrWebsite;
}
if (answers.languages.length > 0) mentorDetails.languages = answers.languages;
if (!isEmpty(answers.timezone.trim()))
mentorDetails.timezone = answers.timezone;
if (!isEmpty(answers.previousMentor.trim()))
mentorDetails.previousMentor = answers.previousMentor;
if (answers.mentorshipArea.length > 0)
mentorDetails.mentorshipArea = answers.mentorshipArea;
if (!isEmpty(answers.hoursAvailable.trim()))
mentorDetails.hoursAvailable = answers.hoursAvailable;
if (answers.menteePref.length > 0)
mentorDetails.menteePref = answers.menteePref;
if (!isEmpty(answers.otherPref.trim())) {
let menteePrefs;
let newPref;
if (mentorDetails.menteePref.length !== 0)
menteePrefs = mentorDetails.menteePref;
else menteePrefs = [];
newPref = answers.otherPref.split(',');
menteePrefs = menteePrefs.concat(newPref);
mentorDetails.menteePref = menteePrefs;
}
if (answers.prefferedOutcomes.length > 0)
mentorDetails.prefferedOutcomes = answers.prefferedOutcomes;
if (!isEmpty(answers.otherOutcomes.trim())) {
let outcomes;
let newPref;
if (mentorDetails.prefferedOutcomes.length !== 0)
outcomes = mentorDetails.prefferedOutcomes;
else outcomes = [];
newPref = answers.otherPref.split(',');
outcomes = outcomes.concat(newPref);
mentorDetails.prefferedOutcomes = outcomes;
}
if (!isEmpty(answers.discussAfter.trim()))
mentorDetails.discussAfter = answers.discussAfter;
if (answers.skillMentorship.length > 0)
mentorDetails.skillMentorship = answers.skillMentorship;
if (answers.researchAreas.length > 0)
mentorDetails.researchAreas = answers.researchAreas;
if (answers.careerAdvice.length > 0)
mentorDetails.careerAdvice = answers.careerAdvice;
if (!isEmpty(answers.workshopReviewer))
mentorDetails.workshopReviewer = answers.workshopReviewer;
if (!isEmpty(answers.peerReviewedPubs.trim()))
mentorDetails.peerReviewedPubs = answers.peerReviewedPubs;
if (!isEmpty(answers.topTierReviewer.trim()))
mentorDetails.topTierReviewer = answers.topTierReviewer;
if (!isEmpty(answers.topTierPub.trim()))
mentorDetails.topTierPub = answers.topTierPub;
if (!isEmpty(answers.highImpactReviewer.trim()))
mentorDetails.highImpactReviewer = answers.highImpactReviewer;
if (answers.conferencePreference.length > 0)
mentorDetails.conferencePreference = answers.conferencePreference;
if (!isEmpty(answers.otherConferences.trim())) {
let otherconferences = answers.otherConferences.split(',');
let conferences = mentorDetails.conferencePreference;
conferences = conferences.concat(otherconferences);
mentorDetails.conferencePreference = conferences;
}
if (!isEmpty(answers.peerReviewedHighImpact))
mentorDetails.peerReviewedHighImpact = answers.peerReviewedHighImpact;
return mentorDetails;
};
I had added a package I needed in functions/index.js to my frontend with
/projectroot $ npm install -s [package]
, in stead of going into the /functions folder with the terminal and add it there to the /functions/package.json for node.js
/projectroot/functions $ npm install -s [package]
Why it causes so much trouble is because things work fine in emulator developer modus, but when you deploy it only sais it has an error, but doesn't tell you what the problem is.
More info on this: Firebase function failing to deploy
According to the error message, there isn't a whole lot of information about the problem you're presenting.
I know you used firebase –-debug deploy to retrieve the error message, and it returned an error on the user code, but what I would advise is that you look into the issue by viewing the log using firebase functions:log, which would be a lot easier.
There will be a visible representation of the exact issue. It could be something as simple as a missing package in some cases.
You can also use the following:
firebase functions:log --only <FUNCTION_NAME>
To have a better understanding of this command, you can access the Write and view logs.
Your firebase.json must include the following JSON code and it has to be similar to this in your case:
"hosting": {
"public": "public",
"rewrites" :[{
"source" : "**",
"function" : "api"
}],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}

Connect to kubernetes with AWS Lambda function

I am trying to create a lambda function for an Alexa skill that will connect to an EKS cluster. I am creating the cluster using with Terraform and hosting it on AWS. I am not sure if I am correctly exporting my function correctly and would appreciate some feedback.
const Alexa = require('ask-sdk')
const Client = require('kubernetes-client').Client
const connect = require("./connect");
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest";
},
handle(handlerInput) {
console.log("Launch Request Handler Called");
let speechText =
"KubeVoice Test";
let repromptText =
"I did not receive any input. You can say, Connect to Cluster.";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(repromptText)
.getResponse();
}
};
//Handler for connecting
const KubernetesConnect = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.request.intent.name === "Connect"
);
},
handle(handlerInput) {
let connectToCluster = connect.connect();
let speechText = "connected to cluster";
return handlerInput.responseBuilder.speak(speechText).getResponse();
}
};
const UnhandledHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error Handler : ${error.message}`);
return handlerInput.responseBuilder.speak(
"Sorry, I am unable to process your request, ask me to connect"
).getResponse();
}
};
exports.handler = Alexa.SkillBuilders.custom().
addRequestHandlers(
LaunchRequestHandler,
KubernetesConnect,
)
.addErrorHandlers(UnhandledHandler)
.lambda();
And the code for connecting to the eks cluster is taken from the Godaddy Kubernetes client example
const Client = require('kubernetes-client').Client
async function connect() {
try {
const client = new Client({
config: {
url: process.env.K8S_CLUSTER_HOST,
auth: {
provider: {
type: 'cmd',
config: {
'cmd-path': 'aws-iam-authenticator',
'cmd-args': 'token -i' + process.env.K8S_AUTH_TOKEN,
'cmd-env': {
AWS_PROFILE: process.env.AWS_PROFILE
},
'token-key': 'status.token'
}
}
},
insecureSkipTlsVerify: true
},
version: process.env.K8S_CLUSTER_VERSION
});
}
catch (err) {
console.error('Error: ', err);
}
}
module.exports.connect = connect;
This is the error I am getting
2021-04-10T13:45:14.982Z c1c8c985-5eb0-43dd-a041-5a077ca12b6c INFO Error Handler : Cannot read property 'type' of undefined
was missing .requestEnvelope on the line for the connect intent. The code functions now, just need to sort IAM roles for the cluster!

How to consume a RESTful API in Node.js

I'm new to Node.js and I'm creating a simple pagination page. The REST API works fine, but consuming it has left me in limbo.
Here is the REST API (other parts have been taken out for brevity)
const data = req.query.pageNo;
const pageNo =
(typeof data === 'undefined' || data < 1) ? 1 : parseInt(req.query.pageNo);
let query = {};
const total = 10;
query.skip = (total * pageNo) - total;
query.limit = total;
try {
const totalCount = await Users.countDocuments();
const pageTotal = Math.ceil(totalCount / total);
const users = await Users.find({}, {}, query);
return res.status(200).json(users);
} catch (error) {
console.log('Error ', error);
return res.status(400).send(error)
};
};
When I return the json with just the 'users' object, like so return res.status(200).json(users); the page renders correctly, but when I pass in other objects like what I have in the code, it fails. This is how I'm consuming the API:
const renderHomepage = (req, res, responseBody) => {
let message = null;
if (!(responseBody instanceof Array)) {
message = 'API lookup error';
responseBody = [];
} else {
if (!responseBody.length) {
message = 'No users found nearby';
}
}
res.render('users-list', {
title: 'Home Page',
users: responseBody,
message: message
});
}
const homelist = (req, res) => {
const path = '/api/users';
const requestOptions = {
url: `${apiOptions.server}${path}`,
method: 'GET',
json: true,
};
request(
requestOptions,
(err, {statusCode}, body) => {
if (err) {
console.log('Ther was an error ', err);
} else if (statusCode === 200 && body.length) {
renderHomepage(req, res, body);
} else if (statusCode !== 200 && !body.length) {
console.log('error ',statusCode);
}
}
);
}
I've searched extensively on both here and other resources but none of the solutions quite answers my question. I hope someone could be of help

Firestore Functions: handle map value

First of all I have to say that I have and intermediate experience on Java and very very basical with JS.
I'm trying to remove expired tokens from my database, for achieve that I did:
function sendNotificationToUser(payload, userSnapshot) {
const userId = userSnapshot.id;
const user = userSnapshot.data();
let tokenMap = user.tokens;
const tokens = Object.keys(tokenMap);
const options = {priority: "high"};
admin.messaging().sendToDevice(tokens, payload, options).then(response => {
// For each message check if there was an error.
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') {
tokenMap.delete(tokens[index]);
}
} else{
console.log("Sent to user: ", user.name, " " ,user.surname, " notification: ", payload, " tokens: ", tokens[index]);
}
});
usersRef.doc(userId).update({
tokens: tokenMap
});
});
}
No problem to get the keys of the tokenMap, but looks like I can't remove entries with .delete(), since I got that in my Log:
TypeError: tokenMap.delete is not a function
at response.results.forEach (/user_code/index.js:127:36)
at Array.forEach (native)
at admin.messaging.sendToDevice.then.response (/user_code/index.js:122:26)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
What is the reason??
Solved:
delete tokensObj[tokensArray[index]];
Full code:
function sendNotificationToUser(payload, userSnapshot) {
const user = userSnapshot.data();
let tokensObj = user.tokens;
const tokensArray = Object.keys(tokensObj);
let toUpdate = false;
const options = {priority: "high"};
admin.messaging().sendToDevice(tokensArray, payload, options).then(response => {
// For each message check if there was an error.
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') {
toUpdate = true;
delete tokensObj[tokensArray[index]];
}
} else {
console.log("Sent to user: ", user.name, " ", user.surname, " notification: ", payload, " token: ", tokensArray[index]);
}
});
if (toUpdate === true) {
userSnapshot.ref.update({ tokens: tokensObj }).catch(error => console.log(error));
}
});
}

Resources