Unable to upload file using googleapis on Google Drive - node.js

I have a problem with the file upload on google drive using the package googleapis (v.40):
In my web application (written in Vue js) i need to upload an image file of user 'A' into the google drive space of user 'B' using googleapis.
For this, i have created a "service-account" from the google console platform (of user B) and generated the credentials.json for the API access. (JWToken,service-to-service scenario)
In my web application, after getting the AccessToken by means the json credentials of the service account, i'm ready to upload the file. But, when i call the drive.files.create(...) api i get the following error:
Invalid multipart request with 0 mime parts.
Here some code:
...
// get google api
const {google} = require("googleapis");
const drive = google.drive("v3");
// get authorization token
let authToken = await getAuthToken() // it perfectly works
console.log(authToken)
let metadata = {
name: name,
parents: [idOfTheParentFolder]
}
let media = {
mimeType: 'image/jpeg',
body: file
}
let objImage = {
auth: authToken,
resource:metadata,
media: media,
fields: 'id',
}
drive.files.create(objImage, function (error, success) {
if (!error) {
...
}
else{
// here i got the error in question
}
})
I've tried exactly this code in a single node js file and it works fine, but it doesn't works in the web browser Vue application.
Let me say first that the API for showing the files (drive.files.list()) and the API for create a folder (drive.files.create()) they work just fine in my web application.
Any suggestion?

Related

Pass file uploaded via HTTP POST to another API

I have a Node.js (16.13.1) REST API using Express and one of my endpoints receives one or more uploaded files. The client (web app) uses FormData into which the files are appended. Once they're submitted to my API, the code there uses multer to grab the files from the request object.
Now I'm having trouble trying to send those same files to another API. multer attaches the files to req.files and each file object in that array has several properties one of which is buffer. I tried using the stream package's Duplex object to convert this buffer to a stream so that I could append the file to another FormData object, but when the server the second API is running on receives the request, I get an error from the web server saying that "a potentially dangerous request.form value was detected from the client.".
Any suggestions?
I am working on a nest project I was also facing this issue did some research and found that we need to create a Readable from the Buffer of that file and it's working for me.
// Controller
#UseInterceptors(FileInterceptor('file'))
async uploadFile(#UploadedFile() file: Express.Multer.File) {
return this.apiservice.upload(file);
}
// Service
uploadFile(file: Express.Multer.File) {
const readstream = Readable.from(file.buffer)
console.log(readstream)
const form = new FormData();
form.append('file', file, { filename: extra.filename });
const url = `api_endpoint`;
const config: AxiosRequestConfig = {
headers: {
'Content-Type': 'multipart/form-data'
},
};
return axios.post(url, form, config);
}

Teams Messaging Extensions Config Auth

I created a Message extension, using the sample,
https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/52.teams-messaging-extensions-search-auth-config
and I am following this doc for authentication,
https://learn.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/how-to/add-authentication#:~:text=If%20your%20service%20requires%20user,can%20use%20the%20messaging%20extension.&text=User%20issues%20a%20query%2C%20or,inspecting%20the%20Teams%20user%20ID.
Technology Used :- Node Js
The issue I am facing is, I am unable to open the auth webpage when installing the Message extension in teams, It directly open the message extension window instead of web page.
// The user has requested the Messaging Extension Configuration page settings url.
const userSettings = await this.userConfigurationProperty.get(context, '');
const escapedSettings = userSettings ? querystring.escape(userSettings) : '';
// I am able to reach here, but that url which is returning is not opening.
return {
composeExtension: {
type: 'config',
suggestedActions: {
actions: [
{
type: ActionTypes.OpenUrl,
value: `${process.env.SiteUrl}/public/searchSettings.html?settings=${escapedSettings}`
}
]
}
}
};
}
In manifest file, I passed the valid url as mentioned in document, but still that auth page is not opening.
If you have any reference or any document related to this, please share.
Thanks
Here is message extension sample using node.js and including SSO: https://github.com/pnp/teams-dev-samples/tree/master/samples/msgext-graph-action-docreview

Firebase Storage access token creation in node.js [duplicate]

This question already has answers here:
Get Download URL from file uploaded with Cloud Functions for Firebase
(25 answers)
Closed 2 years ago.
Basically I have two ways of uploading files to the firebase storage:
Frontend calls backend with image url, the backend downloads the image and uploads via bucket.upload (which I like, because I can set the storageAccessToken)
The User uploads directly via frontend with a signed url that got generated in the backend. (which I dislike because I can't set a storageAccessToken)
I have a onFinalize trigger that gets called everytime a new object is stored in the firebase storage.
In this trigger I want to create a firestore doc for this particular object that got added.
In order to get the file information I use probe-image-size.
The problem is that I need a download link for the file and without a storageAccessToken I can not download the file as far as I know.
Basically the question is: can I add a storageAccessToken in the onFinalize trigger or could I add the storageAccessToken when I upload a file via frontend with the signedUrl?
If I correctly understand your question, you would like, in a Cloud Function ("onFinalize trigger") to create a Firestore document which contains, among other info (from probe-image-size), a signed URL.
You can get a signed URL through a Cloud Function, as follows, without the need for a storageAccessToken:
exports.generateSignedURL = functions.storage.object().onFinalize(async object => {
try {
const bucket = admin.storage().bucket(object.bucket);
const file = bucket.file(object.name);
const signedURLconfig = { action: 'read', expires: '08-12-2025' }; // For example...
const signedURLArray = await file.getSignedUrl(signedURLconfig);
const url = signedURLArray[0];
await admin.firestore().collection('signedURLs').add({ fileName: object.name, signedURL: url })
return null;
} catch (error) {
console.log(error);
return null;
}
});

First step on Google API + GMAIL = bad request

I'm very new on Google API, Eventually I want to send emails using it. But for now I'm trying something a little bit simpler (and then build it up).
List all emails in the inbox.
From Gmail > API > Reference, I followed these steps:
On Google API Console:
Created my application.
Under API & Services > Credentials I created a user with Project/Owner role (just to make sure there is no permission problems in this step).
Then I created a key and download the json file.
At API & Services > Library I enabled Gmail.
And using the Reference I put together this snippet:
app.ts
import { google } from 'googleapis';
import credentials from './credentials';
async function main() {
const auth = new google.auth.GoogleAuth({
credentials,
scopes: [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.metadata'
]
});
const authClient = await auth.getClient();
const gmail = google.gmail({ version: 'v1', auth: authClient });
const data = await gmail.users.messages.list({ userId: 'me' });
console.log(data);
}
main().catch(console.log);
package.json
...
"dependencies": {
googleapis": "^48.0.0"
}
...
Every time I ran this snippet I got:
[01] GaxiosError: Bad Request
[02] at Gaxios._request (~\node_modules\gaxios\build\src\gaxios.js:85:23)
...
[06] response: {
...
[35] status: 400,
[36] statusText: 'Bad Request',
[37] request: {
[38] responseURL: 'https://www.googleapis.com/gmail/v1/users/me/messages'
...
I tried many diferent configurations on Google API Console. Tried to change the scope (list of urls from line 8 to 12) for many others, change the credentials.json to a .js and .ts format, put in a global variable (GOOGLE_APPLICATION_CREDENTIALS) instead of a direct import. But despite of all my attempts, I got aways the same error.
How can I fix that?
Check out example from here which does exactly what you want. They seem use a sampleclient instead of a credentials library.

Chrome Web Store 'You don't have access to licensing data for App ID:'

I have an offline Chrome Web App I want to sell through the web store.
It has a server backend. I'd like the server to check license data. How do I do that?
Here's the API. Here's a Java HowTo. Here's a OAuth-JWT lib for nodejs. I made a new client-id as described in the lib's readme.
I get this response:
{ error:
{ errors: [ [Object] ],
code: 403,
message: 'You don\'t have access to licensing data for App ID: aaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}
}
How do I access license data for my app, in my server?
Mike
Here's the code:
var appId = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
var userId = '1111111111111111111111';
// obtain a JWT-enabled version of request
var request = require('google-oauth-jwt').requestWithJWT();
request({
url: 'https://www.googleapis.com/chromewebstore/v1.1/licenses/'+appId+'/'+userId,
jwt: {
// use the email address of the service account, as seen in the API console
email: '11111111111-aaaaaaaaaaaaaaaaaaaaaaaa#developer.gserviceaccount.com',
// use the PEM file we generated from the downloaded key
keyFile: 'config/keys/app-11111111111111.pem',
// specify the scopes you wish to access - each application has different scopes
scopes: ['https://www.googleapis.com/auth/chromewebstore.readonly']
}
}, function (err, res, body) {
console.log(JSON.parse(body));
});
I've spent way to much time on this and other small problems with the Chrome Webstore. Going with Stripe.com, Braintree, or similar.

Resources