Firebase: Delete files in Cloud Starage using Cloud Functions - node.js

I'm trying to delete all files, related to some specific entry in Realtime Database, from Cloud Storage on the entry deletion, using Cloud Functions. My functions looks as fallows:
exports.onDeleteRequest = functions.database.ref('/requests/{requestid}/').onDelete(event => {
const storage = functions.config().firebase.storageBucket;
const userId = event.data.previous.child('uid').val();
const requestId = event.params.requestid;
const path = storage + '/photos/' + userId + '/' + requestId;
console.log('path: ', path);
return gcs.bucket(path).delete().then(function() {
console.log("Files removed");
}).catch(function(error) {
console.error("Failed removing files", error);
});
});
But, I continue getting following error in log:
Failed removing files { ApiError: Not Found
at Object.parseHttpRespBody (/user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:192:30)
at Object.handleResp (/user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:132:18)
at /user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:465:12
at Request.onResponse [as _callback] (/user_code/node_modules/#google-cloud/storage/node_modules/retry-request/index.js:182:7)
at Request.self.callback (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:186:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:1163:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
code: 404,
errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
response: undefined,
message: 'Not Found' }
path: photos/gRplE2ujnIb93Ji5HSzEj3O4i3d2/-L-DHkKMhvLH9l6dWmR2
All subfolders are 100% existing at the time of the function execution. Can anyone help?
I apologize for asking the question, that, without a doubt, was asked before in one way or another, but I didn't find any suggestion of how to solve this issue or why does it occurs in the first place.

Related

Expected argument of type "string", "stdClass" given Error

I'm using mailchimp-api-v3 for nodejs. I'm currently trying to update a user's tag but sometimes this error pops up and I have no idea what it means. I searched around but it doesn't seem like a lot of devs have encountered it.
Any suggestions are welcomed.
try {
await mailchimp.post('/lists/' + listIDUsers + '/members/' + crypto.createHash('md5').update(profileSnap.val().email.toLowerCase()).digest("hex") + '/tags', {
tags: [{name: "traveler", status: "active"}]
});
} catch (error) {
if (error.status === 404) {
await mailchimp.post('/lists/' + listIDUsers + '/members', {
email_address: profileSnap.val().email,
status: 'subscribed',
merge_fields: {
"FNAME": profileSnap.val().firstName,
"LNAME": profileSnap.val().lastName,
"UID": uid,
"EMAIL": profileSnap.val().email
},
tags: [{name: "traveler", status: "active"}]
});
} else {
console.log("Issue for: " + uid);
console.log(error);
}
The error:
Error: Expected argument of type "string", "stdClass" given
at Request._callback (/srv/node_modules/mailchimp-api-v3/index.js:506:30)
at Request.self.callback (/srv/node_modules/request/request.js:185:22)
at emitTwo (events.js:126:13)
at Request.emit (events.js:214:7)
at Request.<anonymous> (/srv/node_modules/request/request.js:1161:10)
at emitOne (events.js:116:13)
at Request.emit (events.js:211:7)
at IncomingMessage.<anonymous> (/srv/node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
Okay, I've decided to go ahead and reach out to Mailchimp since this question has been left unanswered for a few days! They got back to me stating that the reason I'm getting the error above is that because I'm trying to set a tag for a subscriber right after adding the subscriber so the system wasn’t able to successfully add the tag because the subscriber hashed id wasn’t quiet created yet.
So all I needed was the following line of code to have my function wait 10 seconds before setting the tag.
await new Promise(resolve => setTimeout(resolve, 10000));
await mailchimp.post('/lists/' + listIDUsers + '/members/' + crypto.createHash('md5').update(profileSnap.val().email.toLowerCase()).digest("hex") + '/tags', {
tags: [{name: "traveler", status: "active"}]
});

AWS SDK and NODE JS --> UnknownEndpoint

I have followed this guide: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/ec2-example-creating-an-instance.html
When I run the code below - I get the UnknowEndPoint error.
I have created an AWS IAM user and added the user to a group with the policy name "IAMFullAccess" - I don't know which other policy would fit (I can see in the AWS dashboard that my credentials has been used programmatically - So I guess this part works well...)?
I have placed my credentials in the .aws folder in a file named credentials.
I am not sure what actually to put inside the 'KeyName' below - currently I have entered the Key Pair Name I find by clicking on one of my existing AWS EC2 instances in the dashboard. Is this correct?
Is there some security group or similar I need to edit - to able to connect NodeJS to my AWS account? Otherwise I have no clue what to do?
In start.js file:
process.env.AWS_SDK_LOAD_CONFIG=1;
var AWS_SDK = require('./aws_sdk');
var aws_sdk = new AWS_SDK();
aws_sdk.CopyInstance();
In aws_sdk.js file:
function AWS_SDK() {
this.CopyInstance = function() {
try {
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
//Set the region
AWS.config.update({region: 'us-east-2a'});
var instanceParams = {
ImageId: 'ami-0...',
InstanceType: 't1.micro',
KeyName: '<Key_name>',
MinCount: 1,
MaxCount: 1
};
// Create a promise on an EC2 service object
var instancePromise = new AWS.EC2({apiVersion: '2016-11-15'}).runInstances(instanceParams).promise();
// Handle promise's fulfilled/rejected states
instancePromise.then(
function (data) {
console.log(data);
var instanceId = data.Instances[0].InstanceId;
console.log("Created instance", instanceId);
// Add tags to the instance
var tagParams = {
Resources: [instanceId], Tags: [
{
Key: 'Name',
Value: 'SDK Sample'
}
]
};
// Create a promise on an EC2 service object
var tagPromise = new AWS.EC2({apiVersion: '2016-11-15'}).createTags(tagParams).promise();
// Handle promise's fulfilled/rejected states
tagPromise.then(
function (data) {
console.log("Instance tagged");
}).catch(
function (err) {
console.error(err, err.stack);
});
}).catch(
function (err) {
console.error(err, err.stack);
});
}
catch(e){
wl.info('Error: ' + e);
}
}
function create() {
if(globalAWS === null)
globalAWS = new AWS_SDK();
return globalAWS;
}
module.exports = create;
ERROR:
{ UnknownEndpoint: Inaccessible host: ec2.us-east-2a.amazonaws.com'.
This service may not be available in theus-east-2a' region.
at Request.ENOTFOUND_ERROR (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\event_listeners.js:486:46)
at Request.callListeners (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:683:14)
at ClientRequest.error (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\event_listeners.js:325:22)
at ClientRequest. (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\http\node.js:93:19)
at ClientRequest.emit (events.js:182:13)
at ClientRequest.EventEmitter.emit (domain.js:442:20)
at TLSSocket.socketErrorListener (_http_client.js:391:9)
at TLSSocket.emit (events.js:182:13) message: 'Inaccessible host: ec2.us-east-2a.amazonaws.com\'. This service may not be
available in theus-east-2a\' region.', code: 'UnknownEndpoint',
region: 'us-east-2a', hostname: 'ec2.us-east-2a.amazonaws.com',
retryable: true, originalError: { Error: getaddrinfo ENOTFOUND
ec2.us-east-2a.amazonaws.com ec2.us-east-2a.amazonaws.com:443
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:57:26)
message:
'getaddrinfo ENOTFOUND ec2.us-east-2a.amazonaws.com ec2.us-east-2a.amazonaws.com:443',
errno: 'ENOTFOUND',
code: 'NetworkingError',
syscall: 'getaddrinfo',
hostname: 'ec2.us-east-2a.amazonaws.com',
host: 'ec2.us-east-2a.amazonaws.com',
port: 443,
region: 'us-east-2a',
retryable: true,
time: 2019-01-14T20:03:42.177Z }, time: 2019-01-14T20:03:42.177Z } 'UnknownEndpoint: Inaccessible host:
ec2.us-east-2a.amazonaws.com\'. This service may not be available in
theus-east-2a\' region.\n at Request.ENOTFOUND_ERROR
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\event_listeners.js:486:46)\n
at Request.callListeners
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:106:20)\n
at Request.emit
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:78:10)\n
at Request.emit
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:683:14)\n
at ClientRequest.error
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\event_listeners.js:325:22)\n
at ClientRequest.
(D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\http\node.js:93:19)\n
at ClientRequest.emit (events.js:182:13)\n at
ClientRequest.EventEmitter.emit (domain.js:442:20)\n at
TLSSocket.socketErrorListener (_http_client.js:391:9)\n at
TLSSocket.emit (events.js:182:13)'
Process finished with exit code 0
If I change the REGION to "us-east-2" (delete the 'a' at the end) the error changes to this:
{ Unsupported: The requested configuration is currently not supported. Please check the documentation for supported configurations.
at Request.extractError (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\services\ec2.js:50:35)
at Request.callListeners (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:683:14)
at Request.transition (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:22:10)
at AcceptorStateMachine.runTo (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\state_machine.js:14:12)
at D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\state_machine.js:26:10
at Request.<anonymous> (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:38:9)
at Request.<anonymous> (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\request.js:685:12)
at Request.callListeners (D:\Workspace\BitBucket\Test\node_modules\aws-sdk\lib\sequential_executor.js:116:18)
message:
'The requested configuration is currently not supported. Please check the documentation for supported configurations.',
code: 'Unsupported',
time: 2019-01-14T20:31:55.954Z,
requestId: '815a44e2-5d0d-453e-a4ff-6faac2695064',
statusCode: 400,
retryable: false,
retryDelay: 51.269952198296934 } 'Unsupported: The requested configuration is currently not supported. Please check the documentation for supported configurations.\n at Request.extractError (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\services\\ec2.js:50:35)\n at Request.callListeners (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\sequential_executor.js:106:20)\n at Request.emit (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\sequential_executor.js:78:10)\n at Request.emit (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\request.js:683:14)\n at Request.transition (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\request.js:22:10)\n at AcceptorStateMachine.runTo (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\state_machine.js:14:12)\n at D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\state_machine.js:26:10\n at Request.<anonymous> (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\request.js:38:9)\n at Request.<anonymous> (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\request.js:685:12)\n at Request.callListeners (D:\\Workspace\\BitBucket\\Test\\node_modules\\aws-sdk\\lib\\sequential_executor.js:116:18)'
Update 1:
I changed the REGION from to 'us-est-2' and now also updated my ~/.aws/config file (before the file only contained 1 line/row: 'region=us-west-2'):
[default]
region=us-west-2
output=json
Now I get this error (when I try to decode it in the CMD) - I still don't understand what extra roles I have to give/grant my IAM-AWS user to be able read the error message?
An error occurred (AccessDenied) when calling the DecodeAuthorizationMessage operation: User: arn:aws:iam::0046xxxxxxx:user/user_name is not authorized to perform: sts:DecodeAuthorizationMessage
You have configured your AWS region as us-east-2a. That isn't a region, that is an availability zone. Your region should be configured as us-east-2.
After I added the IAM role: "AdministratorAccess" all issues were gone :) The question is now - which role(s) are actually needed to be granted for it to work..."AdministratorAccess" was just for testing purpose.

Unable to load default credentials in node.js google translate

I need to translate some text in node.js using google translate. I end up getting the following Error: Could not load the default credentials. Browse to here to get more details. This problem has costed me more than 48 hours. I have followed all the instructions in that link but problem still persists. Please someone point what is it that I've missed.
Error log:
ERROR: Error: Could not load the default credentials. Browse to
https://developers.google.com/accounts/docs/application-default-credentials
for more information.
at /user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/auth/googleauth.js:316:21
at /user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/auth/googleauth.js:346:7
at Request._callback (/user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/transporters.js:70:30)
at self.callback (/user_code/node_modules/#google-cloud/translate/node_modules/request/request.js:186:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/user_code/node_modules/#google-cloud/translate/node_modules/request/request.js:878:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at Socket.socketErrorListener (_http_client.js:309:9)
function translateText(Text, Target) {
// [START translate_translate_text]
// Imports the Google Cloud client library
const Translate = require('#google-cloud/translate');
// Your Google Cloud Platform project ID
const projectId = 'xxxxxxxxxx';
// Instantiates a client
const translate = new Translate({
projectId: projectId,
});
// Translates some text into Russian
translate
.translate(Text, Target)
.then(results => {
const translation = results[0];
console.log(`Text: ${text}`);
console.log(`Translation: ${translation}`);
return translation;
})
.catch(err => {
console.error('ERROR:', err);
});
}

Node googleapis: getting Error: invalid_request after short period of time

I'm using the node googleapis library to make requests to the youtube data api. I'm starting of with authenticating a user using passport the passport-youtube-v3 library. Everything works fine. I'm able to authenticate and I can make authorized requests to the youtube data api. But after a certain amount of time (around 1-2h) the credentials seem to have expired or just become invalid and I get the following error:
{ Error: Invalid Credentials
at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:85:15)
at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:286:16)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:926:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
code: 401,
errors:
[ { domain: 'global',
reason: 'authError',
message: 'Invalid Credentials',
locationType: 'header',
location: 'Authorization' } ] }
I understand that auth tokens expire after some time. But according to the documentation this shouldn't happen before 6 months of inactivity. Also I'm not making an excessive amount of requests that could render the tokens invalid. Nevertheless I tried to implement a manual toke refresh of the access token like this:
const fetch = (user, ressource, operation, opts) => {
let oauth2Client = new OAuth2();
let client = google.youtube({ version: 'v3',auth: oauth2Client })[ressource][operation];
oauth2Client.credentials = {
access_token: user.youtube.token,
refresh_token: user.youtube.refreshToken
};
return new Promise((success, failure) => {
client(opts, function(err, data, response) {
if (err)
if(err.code === 401)
oauth2Client.refreshAccessToken(function(err, tokens) {
console.log(err);
});
else
failure(err);
if (data)
success(data);
});
});
}
I'm not sure if I implemented this correctly of if it even makes sense to do this. I get the following error:
{ Error: invalid_request
at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:81:15)
at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:286:16)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:926:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9) code: 400 }
What else could be the issue when getting the first error? Is it possible that the access token expires so quickly? If so, how do I refresh it correctly?
Any help is greatly appreciated!
It seems like the problem was that I didn't instantiate OAuth2 correctly. I didn't pass the credentials of my app to the constructor upon creation. Everything seems to work now.
let oauth2Client = new OAuth2(
clientID,
clientSecret,
callbackURL
);
The only confusion I still have is as to why it worked for a couple of requests before it started to throw the error described above.

Cloud Functions for Firebase Image download function Error

I am building a web application using Firebase and the new feature Cloud Functions for Firebase. I have created a function that takes a URL and downloads the image into a 64-bit encoded string as below using the node modules request and request-promise-native:
module.exports = {
downloadImageFromUrl: function (url) {
var options = {
method: 'GET',
uri: url,
resolveWithFullResponse: true,
simple: false,
family: 4
};
return rp.get(options)
.then(function (res) {
return "data:" + res.headers["content-type"] + ";base64," + new Buffer(res.body).toString('base64');
})
.catch(function (error) {
console.log("ERROR GETTING image", error);
return error;
});
}
};
The top function works perfectly running locally but once on firebase it gives the error:
RequestError: Error: getaddrinfo EAI_AGAIN lh6.googleusercontent.com:443
at new RequestError (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/errors.js:14:15)
at Request.plumbing.callback (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:87:29)
at Request.RP$callback [as _callback] (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:46:31)
at self.callback (/user_code/node_modules/request/request.js:188:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/user_code/node_modules/request/request.js:884:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at TLSSocket.socketErrorListener (_http_client.js:310:9)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)
at connectErrorNT (net.js:1020:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9)
I am calling the function in the firebase auth trigger when a user is created as below:
exports.createUser = functions.auth.user().onCreate(event => {
if (event.data.photoURL) {
utils.downloadImageFromUrl(event.data.photoURL)
.then(function(res){
console.log("User Photo", res);
})
.catch(function(error){
console.log("Error", error);
})
}
});
Any help would be greatly appreciated.
Not entirely sure yet if this is the answer, but after reading the documentation, I read their free plan which says you cannot make any out bound requests. So I guess getting an image from a Url counts as an outbound request. After I start paying for their service, I will come back to verify if this was the problem.

Resources