Access denied to created spreadsheet google node API - node.js

I'm using the google node API to generate a spreadsheet. The 3rd party library I use is the official one (https://github.com/google/google-api-nodejs-client). Here is the code I use to generate the spreadsheet:
var sheets = google.sheets('v4');
sheets.spreadsheets.create({
auth: auth,
resource: {
properties:{
title: "Google export"
}
}
}, (err, response) => {
if (err) {
console.log('The API returned an error: ' + err);
return;
} else {
console.log("Added");
res.send(response);
}
});
It works fine and generate the sheet, when I display the response object, I get the link to the spreadsheet:
spreadsheetUrl: "https://docs.google.com/spreadsheets/d/1XS_QHxPUQcGqZGAzFHkHZV-RSKsv5IpJazcjVpLTYkk/edit"
But when I try to open it in the browser, I can't: You need permission.
The thing is if I click on the Request access button, I think it actually sends a request to the client_email from my credential (user#project-174309.iam.gserviceaccount.com), so it doesn't work.
If I open the spreadsheet programmatically it works...
Does anyone know how to open the generated spreadsheet in a browser?

Here is a solution: https://github.com/google/google-api-nodejs-client/issues/804#issuecomment-327931203
Need to use Google Drive API to grant permissions for this file

Related

Protect the API from being displayed on the browser and programs such as postman

I want to protect the api of the current user, I am starting to learn Node.js but I know that I can get the request information so I wrote this code in which I try to prevent sensitive data from appearing if someone takes the API link and puts it on the browser or postman.
My question: is this method correct to use?.
(sorry for the poor english)
module.exports.current_user_get = (req, res) => {
// If the API is opened by browser or postman
if (req.rawHeaders.indexOf("User-Agent") > -1) {
return res.json({ msg: "Not allowed" });
}
// return user data
};

Create Spreadsheet for read and write using Node js

I Need to create a spreadsheet like a google sheet with user authentication. I have stuck with how to start this project because I couldn't find which NPM module needs to use.
so Kindly help anyone push me in the right direction?
I've been working on similar task few weeks ago.
So here is the mini help for you.
1. Read and follow Node.js Quickstart guide.
Keep an eye on the next concepts like:
Scopes
For example to get a value from a cell we can use spreadsheets.values.get
Scopes for this method are (use 1 of these):
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.readonly
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/spreadsheets
https://www.googleapis.com/auth/spreadsheets.readonly
in node.js it can be an array
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
Token
Once you run for the first time your index.js file the Terminal will ask you for authorization, on finish you will find a token.json in your work directory.
If you change Scopes -> delete token.json from your directory
SpreadsheetId
When you create/edit your spreadsheet you get similar url
https://docs.google.com/spreadsheets/d/1eqRe0ksSwgOoPO0C_mZE6opjS1TlsCU5g1HtkiiILuw/edit#gid=0
1eqRe0ksSwgOoPO0C_mZE6opjS1TlsCU5g1HtkiiILuw is the ID
2. Create custom functions using Google Sheets API Reference
Example how to get cell values:
const sheets = google.sheets({ version: 'v4', auth });
function getCellsValue(cells, callback){
sheets.spreadsheets.values.get({
spreadsheetId: 'spreadsheetId',
range: cells
}, (err, res) => {
if (err) return console.log('Error #1001 : getCellsValue: ' + err);
const output = res.data.values;
if (output.length) {
callback(output);
return output;
} else {
console.log('No data found.');
}
});
}
// here is the example use of this function which output values from D2:D13
getCellsValue("D2:D13", (e) => {
for(let i = 0; i < e.length; i++){
console.log(e[i].toString());
}
}, (err, res) => {
if (err) return console.error('The API returned an error: ', err.message);
})
3. Make a use of Try this API
This is very useful tool.
In case you need more help just use Stackoverflow for more transparency.
Stackoverflow helps you when you make a very detailed question.
I hope this helped you and you can start your Google Sheets API journey.

Cloud Functions for Firebase - action on email verified

Im trying to create a Cloud Function trigger that will execute after email has been verified.
In the Cloud Functions samples I could only find examples on triggers for onCreate and onDelete.
Within the documentation I found something about creating custom action handlers but I don't actually want to replace the standard email verification dialog they have by default, I just want to change the property of a "user" after the email is verified.
Does anyone have any experience with this, and is this even possible? Or is my only option to create my custom verification view/dialog webpage?
I faced this problem and took me a long time to figure it out how to solve so I hope this could help anyone that could get stuck into this too:
1 -> I created a function that was triggered with onCreate() for a new user
exports.sendConfirmationEmail = functions.auth.user()
.onCreate((user) => {
const actionCodeSettings = {
url: 'https://appNextURL.com/',
handleCodeInApp: false//ensure that the link will open into browser
};
return admin.auth().generateEmailVerificationLink(user.email, actionCodeSettings)
.then(async (link) => {
await db.collection('users').doc(user.uid).set({
verificationLink: link,
emailVerified: false
}, {merge: true});
return sendCustomVerificationEmail(user.email, user.displayName, link);
})
.catch((err) => {
console.error("Error:", err);
return Promise.reject(err);
});
});
The generateEmailVErificationLink() will generate the link based on the link we will save on step 3.
The function sendCustomVerificationEmail() is just an internal function that overcomes the standard email firebase send
2 -> Then I created a function that will receive a manual http trigger with the data that would be generated automatically by firebase when sending an automatic email
exports.verifyEmail = functions.https.onRequest((req, res) => {
const {mode, oobCode, apiKey, continueUrl, lang} = req.query;
const link = "https://us-central1-projectId.cloudfunctions.net/verifyEmail/?mode=" + encodeURIComponent(mode) + "&oobCode=" + encodeURIComponent(oobCode) + "&apiKey=" + encodeURIComponent(apiKey) + "&continueUrl=" + encodeURIComponent(continueUrl) + "&lang=" + encodeURIComponent(lang);
return db.collection("users")
.where("verificationLink", "==", link)
.get()
.then(function (querySnapshot) {
querySnapshot.forEach(function (user) {
const userData: UserData = user.data();
console.log("email verified: ", userData.userId);
return admin.auth().updateUser(userData.userId, {
emailVerified: true
}).then(function (userRecord) {
return db.collection('users').doc(userData.userId).set({emailVerified: true}, {merge: true});
});
});
return res.sendStatus(200).end();
}).catch(function (err) {
console.log("error:", err);
return res.sendStatus(403).end();
});
});
As I saved the link in the onCreate() I can now query that link to get who is the user that I am authenticating
3 -> the third step is to change the link in to Firebase Authentication template to the link generated into the 2nd step:
Navigate to Authentication>Templates:
Click on edit icon> Click on customize action URL:
Navigation
Paste the link generated into the step 2 and save:
Save link
Now every link generated automatically will go trought that function you created on step 2 and you will be able to handle the actions you want to happen.
I hope I could be clear.
you could still check for the verification status (at least) on Android with interface UserInfo method isEmailVerified(); eg. in order to send another verification email upon successful login, in case the current user has not yet verified the email address - and show the login screen again. one could as well HTTP trigger a cloud function or update values in the Firebase directly, through the client library. this might also apply to other platform clients, where one can check for the verification status.
this would not be exactly the event when the email just had been verified, but upon each single login attempt one knows the verification status and this value might be merely relevant on the client-side.
Create a publish button so your users trigger your cloud function
Instead of firing the cloud function immediately upon auth.emailVerified, I'm giving my users a 'Publish Profile' button which fires an http cloud function (passing in user.uid). This function looks up the user auth using the passed in user.uid
if user.uid && auth.emailVerified
write auth.emailVerified to each user.post
By default, post document "post.emailVerified" fields start out false, and cannot be written to except via adminFirestore in a cloud function.

Azure Functions - Can it be used with Office Add-in's?

I'm sure there are clever people who can make anything run on Azure functions but does it make sense at all to use it for running Office Add-in's? I read that it's ideal for running small pieces of code and that's what my add-in currently running on Azure as an web app is.
You wouldn't use Azure Functions to build an add-in -- but you absolutely could use it in conjunction with a regular website, for some small server-side processing.
Concrete example: for an Add-in that a colleague and I were building, we needed to obtain a user's GitHub permissions to post Gists on the user's behalf. GitHub uses an "authorization code grant type" flow (see https://developer.github.com/v3/oauth/), so the flow would be as follows:
We pop a dialog (using the recently-introduce Dialog API in Add-ins) to direct the user to https://github.com/login/oauth/authorize, which shows a pretty login UI.
If the user signs in and consents, GitHub sends an authorization code back to us. The code does little good for us in client-side JavaScript, but if we pass it to an Azure Function, we can exchange it for an access token. This must be done in some server-side code (i.e., a web server, or Azure Functions, as a super-lightweight form of a web server) so that we can pass in a Client Secret for the exchange -- which quite naturally wouldn't be secret in sniffable-out client-side JavaScript. Hence putting that code on the server.
If you're curious to see what that code was like, here it is:
var request = require('request');
module.exports = function (context, data) {
context.log('code: ' + data.code);
if ('code' in data) {
request.post({
url: 'https://github.com/login/oauth/access_token',
json: {
client_id: '################',
client_secret: '################',
redirect_uri: '################',
code: data.code
}
}, function (err, httpResponse, body) {
if (err) {
context.log('error: ' + err);
context.res = {
body: {
status: 500,
error: err
}
}
}
else {
context.res = { body: body };
}
context.done();
});
}
else {
context.res = {
status: 400,
body: { error: 'Please pass the GitHub code in the input object' }
};
context.done();
}
}

Error: Body attribute missing in multipart while using googleapis node module

i am using drive version2 to insert a new file to google-drive.
To insert a new file to a google drive using client.files.insert() function
i am getting the following error
Error: Body attribute missing in multipart.
var auth = new googleapis.OAuth2Client();
auth.setCredentials({
access_token: 'accesskey'
});
googleapis.discover('drive', 'v2').execute(function(err, client) {
client.drive.files.insert({ title: 'Test', mimeType: 'application/json' })
.withMedia('application/json', "Hello world")
.withAuthClient(auth)
.execute(function(error,result){
if(error){
console.log(error);
}else{
console.log(result);
}
});
the above code is there in documentation : https://github.com/google/google-api-nodejs-client/
can any on help me!!
Make sure you have enabled the Drive API:
Go to the Google Developers Console.
Select a project.
Select APIs & auth in the left sidebar.
Find the Drive API in the list of available APIs and set its status to ON.

Resources