firebase admin.auth().getUserByProviderUid is not a function - node.js

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

Related

Lambda returns "Malformed Lambda proxy response"

weirdest thing ever, was trying out one of my endpoints in lambda, everything was working a few days back and nothing was changed.
Basically the functions runs fine up until the point where it needs to return a status code, for some reason, then it just returns a 502 and in the API Gateway it states "Malformed Lambda proxy response"
app.post("/api/v1/documents/create", async (req, res) => {
res.setHeader('Content-Type', 'application/json');
const filename = req.body.filename
const partner = req.body.partner
const payload = req.body
const uid = req.body.uid
console.log(payload)
try {
// Initial setup, create credentials instance.
const credentials = PDFServicesSdk.Credentials
.serviceAccountCredentialsBuilder()
.fromFile("./pdfservices-api-credentials.json")
.build();
// Setup input data for the document merge process.
const jsonString = payload,
jsonDataForMerge = jsonString;
// Create an ExecutionContext using credentials.
const executionContext = PDFServicesSdk.ExecutionContext.create(credentials);
// Create a new DocumentMerge options instance.
const documentMerge = PDFServicesSdk.DocumentMerge,
documentMergeOptions = documentMerge.options,
options = new documentMergeOptions.DocumentMergeOptions(jsonDataForMerge, documentMergeOptions.OutputFormat.PDF);
// Create a new operation instance using the options instance.
const documentMergeOperation = documentMerge.Operation.createNew(options);
// Set operation input document template from a source file.
const input = PDFServicesSdk.FileRef.createFromLocalFile('./darbo_sutartis.docx');
documentMergeOperation.setInput(input);
// Execute the operation and Save the result to the specified location.
documentMergeOperation.execute(executionContext)
.then(result => {
console.log("saving File to TMP?")
result.saveAsFile('/tmp/' + uid + '_' + partner + '.pdf')
const checkTime = 1000;
const timerId = setInterval(() => {
const isExists = fs.existsSync('/tmp/' + uid + '_' + partner + '.pdf', 'utf8')
if (isExists) {
console.log("\nFile written -> creating AWS Bucket")
const params1 = {
Bucket: "darbo-manija-docs",
Key: "employment_documents/" + uid + "/" + partner + "/",
};
s3.putObject(params1, (err, data) => {
if (err) {
console.log(err)
} else {
console.log(data)
}
});
console.log("\nAWS Bucket directory created...")
// do something here
console.log("\nUplaoding file to AWS\n")
fs.readFile('/tmp/' + uid + '_' + partner + '.pdf', function (err, data) {
if (err) throw err;
const pdf = data.toString('base64'); //PDF WORKS
const pdfNew = Buffer.from(pdf, 'base64')
const params = {
Bucket: 'darbo-manija-docs/employment_documents/' + uid + "/" + partner,
Key: uid + '_' + partner + '.pdf', // File name you want to save as in S3
Body: pdfNew, // <---------
ContentType: 'application/pdf'
};
// Uploading files to the bucket
s3.upload(params, function (err, data) {
if (err) {
res.status(400).send(JSON.stringify({
message: "ERR",
code: 0
}));
}
console.log(`\nFile uploaded successfully. ${data.Location}`);
console.log("\nCreating entry in Firebase")
var fb_ref = admin.database().ref('/documents');
fb_ref.push({
documentBucket: params.Bucket,
documentKey: params.Key,
candidate: partner,
employer: uid
})
.then(function (fb_ref) {
admin.database().ref('/documents').child(fb_ref.key).update({
documentID: fb_ref.key
})
});
console.log("\nFirebase entry created");
console.log("\nRemoving temp file...")
fs.unlinkSync('/tmp/' + uid + '_' + partner + '.pdf')
res.status(200).send(JSON.stringify({
result: pdf,
code: 100
}));
});
});
clearInterval(timerId)
}
}, checkTime)
})
.catch(err => {
if (err instanceof PDFServicesSdk.Error.ServiceApiError ||
err instanceof PDFServicesSdk.Error.ServiceUsageError) {
console.log('Exception encountered while executing operation', err);
res.status(400).send(JSON.stringify({
result: "Bad request",
code: 400
}));
} else {
console.log('Exception encountered while executing operation', err);
res.status(400).send(JSON.stringify({
result: "Bad request",
code: 401
}));
}
});
} catch (err) {
console.log('Exception encountered while executing operation', err);
}
});
No idea what is happening, read many posts regarding the same error, but none of them seem to have the same setup. Any suggestions? Thanks

I am getting this error via trying to assign roles to the user in the discord via discord.js bot

/app/node_modules/discord.js/src/client/rest/RequestHandlers/Sequential.js:85
new DiscordAPIError(res.request.path, res.body, res.request.method) : err);
^
DiscordAPIError: Missing Permissions
at /app/node_modules/discord.js/src/client/rest/RequestHandlers/Sequential.js:85:15
at /app/node_modules/snekfetch/src/index.js:215:21
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
path: '/api/v7/guilds/715245634218885131/members/235148962103951360',
code: 50013,
method: 'PATCH'
}
This is the error i am facing while the bot got all the permission and is not trying the change the role of owner of someone who is higher in hierarchy.
A year ago this code was working fine but now suddenly it is not working please look at it.
//basic constants and functions
var checked;
var checking = [];
const Discord = require("discord.js");
const {usernameorid, token,usernamesp, roles, apiKey, spreadsheetId, range, unremoveableroles, refreshrate} = require("./config/discord.json");
const { google } = require("googleapis");
const connection = google.sheets({
version: "v4",
auth: apiKey
});
const client = new Discord.Client();
let oldRows = [];
//checking for errors
const logError = error => {
console.error("error log " + new Date());
console.error(error);
};
//the spreadsheet fetching
const fetchRows = async (spreadsheetId, range, sheetsConnection) => {
try {
const response = await sheetsConnection.spreadsheets.values.get({
spreadsheetId: spreadsheetId,
range: range
});
//fetching all data
const rows = response.data.values;
//dividing the data between different array using while loop
var i = 0;
var k=0;
while (i < rows.length) {
const checkrow="";
const rows123= rows[i]
//finally putting all roles together
const therolenames = rows123[1]+","+rows123[2]+","+rows123[3]+","+rows123[4];
assignRoles(rows123[0].trim(), therolenames.trim());
rows123[0]==null;
rows123[1]==null;
rows123[2]==null;
rows123[3]==null;
rows123[4]==null; rows123[1]==null;
roles[1]==null;
roles[2]==null;
roles[3]==null;
roles[4]==null;
therolenames==null;
roles.length=0;
rows123.length=0;
i++;
k++;
}
return rows;
} catch (error) {
logError(error);
}
};
const assignRoles = async (usernames, roleNames) => {
var rolenames1 = roleNames.split(",");
try {
const guildMembers = client.guilds.array()[0].members.array();
//number of all members in the group
const guildRoles = client.guilds.array()[0].roles.array();
// deleting unremovable roles from the list
const Roles2 = guildRoles.filter(Role => !unremoveableroles.includes(Role.name));
// * getting Role instances of role names
const removedRoles = guildRoles.filter(Role => unremoveableroles.includes(Role.name));
const Roles = guildRoles.filter(Role => roleNames.includes(Role.name));
//role number of all members in the group
roleNames.length=0;
// * getting GuildMember instances of usernames and setting roles
guildMembers.forEach(async member => {
const username= member.user.username + "#" + member.user.discriminator;
//check if the first column of spreadsheet matches the userid/username of discord
var UNcheck;
if (usernameorid=="UN"){
UNcheck=username
}else{
UNcheck=member.id
}
if (usernames.includes(UNcheck)) {
const notAssignedRoles = [];
Roles.forEach(role => {
//if (!member.roles.array().includes(Roles)) {
//if (!guildRoles.includes(Roles)) {
checked="no"
//Check whether the roles (discord) are in roles (spreadsheet)
if (Roles.includes(member.roles.array()[1])|| removedRoles.includes(member.roles.array()[1])|| member.roles.array()[1]==null){
}else{checked="yes" }
if (Roles.includes(member.roles.array()[2]) || removedRoles.includes(member.roles.array()[2]) || member.roles.array()[2]==null){
}else{checked="yes"; }
if (Roles.includes(member.roles.array()[3]) || removedRoles.includes(member.roles.array()[3])|| member.roles.array()[3]==null){
}else{checked="yes"; }
if (Roles.includes(member.roles.array()[4])|| removedRoles.includes(member.roles.array()[4]) || member.roles.array()[4]==null){
}else{checked="yes"; }
//Check whether the roles (Spreadsheet) are in roles (Discord)
if (member.roles.array().includes(Roles[0])|| removedRoles.includes(Roles[0]) || Roles[0]==null){
}else{checked="yes"; }
if (member.roles.array().includes(Roles[1]) || removedRoles.includes(Roles[1])|| Roles[1]==null){
}else{checked="yes"; }
if (member.roles.array().includes(Roles[2]) || removedRoles.includes(Roles[2]) || Roles[2]==null){
}else{checked="yes"; }
if (member.roles.array().includes(Roles[3])|| removedRoles.includes(Roles[3]) || Roles[3]==null){
}else{checked="yes"; }
if (checked=="yes"){
notAssignedRoles.push(role);
}
});
if (notAssignedRoles.length > 0) {
await member.removeRoles(Roles2); member.addRoles(Roles);
console.log(
"Assigned " +
notAssignedRoles.map(role => role.name) +
" to " +
username + " ["+member.id+"] on " + new Date().toString()
);
} else {
if (Roles[0]==null && Roles[1]==null && Roles[2]==null && Roles[3]==null) {
member.removeRoles(Roles2);
console.log(username + " ["+member.id+"] has all roles removed on"+ new Date().toString());
}else{
console.log(username + " ["+member.id+"] already has all the roles assigned, checked on "+ new Date().toString());
}
}
}
});
} catch (err) {
logError(err);
}
};
const extractNewEntries = (oldRows, rows) => {
let newRows = [];
if (rows.length > oldRows.length) {
newRows = rows.slice(oldRows.length);
}
newRows.forEach(row => {
oldRows.push(row);
});
return newRows;
};
const extractDiscordIDs = rows => {
return rows.map(user => user[0]);
console.log(rows.map(user => user[0]));
};
client.once(
"ready",
() => {
console.log("Bot started with these settings:");
console.log("• Spreadsheet ID: ");
console.log("• Range: " + range);
console.log("• Roles: " + roles.join(", "));
setInterval(async () => {
console.log("\nChecked for new entries on " + new Date().toString());
let rows;
try {
rows = await fetchRows(spreadsheetId, range, connection);
const newEntries = extractNewEntries(oldRows, rows);
if (newEntries.length > 0) {
console.log(`Found ${newEntries.length} new entries`);
const usernames = extractDiscordIDs(newEntries);
} else {
console.log("No new entries");
}
} catch (err) {
if (rows === undefined) console.error("Google Sheet is empty");
logError(err);
rows = [];
}
}, refreshrate); // refresh rate: 60000 milliseconds == 1 minute
},
logError
);
client.on("error", logError);
const start = async () => {
try {
await client.login(token);
} catch (err) {
logError(err);
setTimeout(start, 30000);
}
};
start();
client.on("disconnect", start);
module.exports = {
fetchRows,
assignRoles,
extractNewEntries,
extractDiscordIDs
};
const express = require("express");
const fs = require("fs");
const app = express();
app.use(express.static("public"));
const listener = app.listen(process.env.PORT, function() {
console.log("Your app is listening on port " + listener.address().port);
});
The complete code is available at
https://github.com/supreen/form2role-bot
please see if you can reproduce the error.
I had solved the problem. The problem was that
1- The role can only assign or remove the roles that are below it.
2- The bot roles that are irremovable and #everyone needs to be added in the config.json file.
They're multiple reasons for this:
The bot doesn't have the permission to manage roles
The member is higher than the member in the role hiarchy
The member is equal than the member in the role hiarchy
The bot is trying to give itself roles that he cannot manage
The bot can't manage the owner's role
Check if any of these are the actual reason you get this error

Magento2 Integration Oauth error - An error occurred validating the nonce

I am trying to activate Magento2, version 2.4.4, integration with expressjs backend.
The callback url is being hit and the data is being stored in the db. Then upon hitting the identity url, the pop up of login for app to be integrated is opened and user logs in.
Following the oauth process as defined at https://devdocs.magento.com/guides/v2.4/get-started/authentication/gs-authentication-oauth.html#pre-auth-token on making the POST request to /oauth/token/request I'm getting the following error -
oauth_problem=An+error+occurred+validating+the+nonce
I cannot figure out the source of this error, please help me fix this as I've been stuck at it since many days.
Following are one of the values calculated for the header Authorization and the post body -
Authorization: 'OAuth oauth_consumer_key=kxw5v6vwr4rm77cn2pxmqxdzdhhkor58, oauth_nonce=Fi9KRqgAmSX7sf32YpCTdPQ15FIY-LyY, oauth_signature=OTUzNWU4ZDViMzljZmM1NTM2MDNiMGQxOTUyMmRmMGRiMjdkZDZmNzY5ZTIxZTZkNGM1MzMzMmRkN2U5ZjcxNQ%3D%3D, oauth_signature_method=HMAC-SHA256, oauth_timestamp=1652694701394, oauth_version=1.0'
POST BODY -
{
oauth_consumer_key: 'kxw5v6vwr4rm77cn2pxmqxdzdhhkor58',
oauth_nonce: 'Fi9KRqgAmSX7sf32YpCTdPQ15FIY-LyY',
oauth_signature: 'OTUzNWU4ZDViMzljZmM1NTM2MDNiMGQxOTUyMmRmMGRiMjdkZDZmNzY5ZTIxZTZkNGM1MzMzMmRkN2U5ZjcxNQ%3D%3D',
oauth_signature_method: 'HMAC-SHA256',
oauth_timestamp: '1652694701394',
oauth_version: '1.0'
}
Following is callback url route code -
router.post('/magento-integration/callback', callbackHandler);
async function callbackHandler(req, res) {
const [{store_base_url, oauth_verifier, oauth_consumer_key, oauth_consumer_secret}] = [req.body];
try {
await saveOAuthCredentials({
store_base_url,
oauth_verifier,
oauth_consumer_key,
oauth_consumer_secret
});
return ApiResponse(res, 200);
} catch (err) {
// TODO: check err and set precise value of response status code and err msg
console.error(err.message)
return ApiResponse(res, 500, {message: err});
}
}
Following is the code for the controller of identity url route -
async function appLogin(req, res) {
// code to validate user
// ......
// Magento2 OAuth token exchange initiation
// Magento2 initiates the token exchange process by requesting the /login endpoint and sends
// url encoded query string params oauth_consumer_key and success_call_back which the front end sends in
// the body, against key queryParams, of the request it makes to /appLogin endpoint of sx-sellerapi.
const {oauth_consumer_key, success_call_back} = req.body.queryParams req.body.queryParams : [{}];
if(oauth_consumer_key && success_call_back){
try{
await runMagentoOAuthKeyX(sellerInfo.id, oauth_consumer_key);
res.redirect(success_call_back);
return;
} catch(err) {
return ApiResponse(res, 400, {message: err})
}
}
// rest of the code for usual login
}
Code for runMagentoOAuthKeyX
async function runMagentoOAuthKeyX(sellerId, oauthConsumerKey) {
try {
const oauthCred = await magentoModel.checkOAuthConsumerKeyExists(oauthConsumerKey, sellerId);
// isNonEmptyObject checks if arg passed is of type Object and has keys
if (isNonEmptyObject(oauthCred)) {
oauthCred.oauth_consumer_key = oauthConsumerKey;
oauthCred.url = `${oauthCred.store_base_url}${OAUTH_TOKEN_ENDPOINTS.request}`;
let requestTokenData;
try{
requestTokenData = await getToken(oauthCred, OAUTH_TOKEN_TYPE.requestToken);
} catch(err){
throw err
}
return Promise.all([
magentoModel.updateOAuthCred(oauthConsumerKey, requestTokenData, OAUTH_TOKEN_TYPE.requestToken),
getToken({...oauthCred, ...requestTokenData,
...{url: `${oauthCred.store_base_url}${OAUTH_TOKEN_ENDPOINTS.access}`}}, OAUTH_TOKEN_TYPE.accessToken)
])
.then(async ([_, accessTokenData]) =>
magentoModel.updateOAuthCred(oauthConsumerKey, accessTokenData, OAUTH_TOKEN_TYPE.accessToken)
)
.catch(err => {
throw err;
});
} else {
throw new Error(`OAuthConsumer key passed is unknown ${oauthConsumerKey}`);
}
} catch (err) {
// TODO: add logging
throw err;
}
Code for getToken()
async function getToken(tokenData, tokenType) {
const {url} = tokenData
const [authHeader, body] = await getAuthHeaderAndBody(tokenData, tokenType);
return axios.post(
url,
body,
{
headers: {
Authorization: authHeader
}
})
.catch(err => {
console.error(err.response.data);
throw err;
});
}
Code for getAuthHeaderAndBody
async function getAuthHeaderAndBody(tokenData, tokenType) {
const oauth_nonce = await genOAuthNonce();
const oauth_timestamp = Date.now();
const {
oauth_consumer_key,
oauth_consumer_secret,
oauth_signature_method,
url,
oauth_token,
oauth_token_secret,
oauth_verifier
} = tokenData;
const tokenList = ['access', 'webAPI'];
const oauthSignature = genOAuthSignature(url, {
oauth_consumer_key,
oauth_consumer_secret,
oauth_signature_method,
oauth_nonce,
oauth_timestamp,
oauth_version: OAUTH_VERSION,
oauth_token: tokenList.includes(tokenType) ? oauth_token : null,
oauth_token_secret: tokenList.includes(tokenType) ? oauth_token_secret : null,
oauth_verifier: OAUTH_TOKEN_TYPE.accessToken === tokenType ? oauth_verifier : null
});
const validParams = Object.entries({
oauth_consumer_key,
oauth_signature_method,
oauth_signature: oauthSignature,
oauth_nonce,
oauth_timestamp,
oauth_version: OAUTH_VERSION,
oauth_token: tokenList.includes(tokenType) ? oauth_token : null,
oauth_verifier: OAUTH_TOKEN_TYPE.accessToken == tokenType ? oauth_verifier : null
})
.filter(([_, val]) => val !== null)
.sort((a, b) => a[0] < b[0] ? -1 : 0);
const authHeaderValue = validParams
.map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)
.join(', ');
const authHeaderStart = [OAUTH_TOKEN_TYPE.requestToken, OAUTH_TOKEN_TYPE.accessToken].includes(tokenType) ? 'OAuth' : 'Bearer';
const authHeader = `${authHeaderStart} ${authHeaderValue}`;
return [authHeader, Object.fromEntries(validParams)];
}
Code for genOAuthNonce -
async function genOAuthNonce() {
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~';
const buff = Buffer.alloc(32);
const result = [];
return new Promise((resolve, reject) => crypto.randomFill(buff, (err, buff) => {
if(err){
reject(err);
}
buff.forEach(c => result.push(charset[c % charset.length]));
resolve(result.join(''));
}));
}
Code for genOAuthSignature
function genOAuthSignature(baseUrl, params, method = 'POST') {
const keysNotInSignature = ['oauth_consumer_secret', 'oauth_token_secret'];
const signatureString = Object.entries(params)
.filter(([key, val]) => val
!= null && !keysNotInSignature.includes(key))
.sort((item1, item2) => item1[0] < item2[0 ] ? -1 : 0)
.map(([key, val]) => `${key}=${val}`)
.join(AUTH_HEADER_DELIMITER);
const baseString = [
encodeURIComponent(method.toUpperCase()),
encodeURIComponent(baseUrl),
encodeURIComponent(signatureString)
].join(AUTH_HEADER_DELIMITER);
const {oauth_consumer_secret, oauth_token_secret} = params;
let signKey = `${encodeURIComponent(oauth_consumer_secret)}${AUTH_HEADER_DELIMITER}`
signKey += oauth_token_secret ? `${encodeURIComponent(oauth_token_secret)}` : '';
const hmac = createHmac('sha256', signKey);
return Buffer.from(hmac.update(baseString).digest('hex')).toString('base64');
}
Found the bugs in the code for invalid Nonce. The issue was with timestamp as I was using Date.now() which returns UTC timestamp in ms whereas magento2 oauth requires it to be in seconds. Also found and fixed the bug in evaluating the signature for oauth token exchange.
In function getAuthHeaderAndBody -
async function getAuthHeaderAndBody(tokenData, tokenType) {
const oauth_nonce = await genOAuthNonce();
// changed below from Date.now() as timestamp must be in seconds.
const oauth_timestamp = parseInt(Date.now() / 1000);
// ... rest of the code
}
In genOAuthSignature
function genOAuthSignature(baseUrl, params, method = 'POST') {
// preceding code
// last line is changed by looking at Magento2 code for validating the signature
return createHmac('sha256', signKey)
.update(baseString, 'binary')
.digest()
.toString('base64');
}

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

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

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