I am not able to give permission to created folder in google drive using google drive APIs - google-drive-api

I have been trying to create a folder with a service account using google drive APIs in google drive. I can see that folder in the google folder list API but not in the google drive GUI.
Here is the code which I tried to create a google drive folder
const { google } = require('googleapis');
require('dotenv').config();
const CREDENTIALS_PATH = process.env.CREDENTIALS_PATH
const scopes = ['https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive']
module.exports = {
createFolder: async () => {
const auth = new google.auth.GoogleAuth({
scopes: scopes,
keyFilename: CREDENTIALS_PATH
})
const service = google.drive({ version: 'v3', auth: auth });
const fileMetadata = {
name: 'newFolder',
mimeType: 'application/vnd.google-apps.folder'
};
try {
const file = await service.files.create({
requestBody: fileMetadata,
fields: 'id',
});
if (!file.data.id) return;
const res2 = await service.permissions
.create({
resource: {
role: "owner",
type: "user",
emailAddress: email,
},
fileId: file.data.id,
transferOwnership: true,
supportsAllDrives: true
}).catch((err) => console.log(err));
console.log(res2.data);
return file.data.id;
} catch (err) {
throw err;
}
}
}
When I give permission to open a folder in drive then it throws an error.
Please find the below error:
GaxiosError: Bad Request. User message: "You cannot share this item because it has been flagged as
response: {
config: {
url: 'https://www.googleapis.com/drive/v3/files/15NJCr03yIXZ5Sv-xwK3ZiuW0UFTIk4IM/permissions?fields=%2A&transferOwnership=true&moveToNewOwnersRoot=true',
method: 'POST',
userAgentDirectives: [Array],
paramsSerializer: [Function (anonymous)],
data: [Object],
headers: [Object],
params: [Object],
validateStatus: [Function (anonymous)],
retry: true,
body: '{"type":"user","role":"owner","emailAddress":"########"}',
responseType: 'json',
retryConfig: [Object]
},
data: { error: [Object] },
headers: {
'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
'cache-control': 'private, max-age=0',
connection: 'close',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
server: 'ESF',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0'
},
status: 400,
statusText: 'Bad Request',
request: {
responseURL: 'https://www.googleapis.com/drive/v3/files/15NJCr03yIXZ5Sv-xwK3ZiuW0UFTIk4IM/permissions?fields=%2A&transferOwnership=true&moveToNewOwnersRoot=true'
}
},
config: {
url: 'https://www.googleapis.com/drive/v3/files/15NJCr03yIXZ5Sv-xwK3ZiuW0UFTIk4IM/permissions?fields=%2A&transferOwnership=true&moveToNewOwnersRoot=true',
method: 'POST',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function (anonymous)],
data: {
type: 'user',
role: 'owner',
emailAddress: '#########'
},
headers: {
'x-goog-api-client': 'gdcl/6.0.3 gl-node/18.5.0 auth/8.7.0',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/6.0.3 (gzip)',
Authorization: 'Bearer #############################################',
'Content-Type': 'application/json',
Accept: 'application/json'
},
params: { fields: '*', transferOwnership: true, moveToNewOwnersRoot: true },
validateStatus: [Function (anonymous)],
retry: true,
body: '{"type":"user","role":"owner","emailAddress":"##############"}',
responseType: 'json',
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [Array],
noResponseRetries: 2,
statusCodesToRetry: [Array]
}
},
code: 400,
errors: [
{
message: 'Bad Request. User message: "You cannot share this item because it has been flagged as inappropriate."',
domain: 'global',
reason: 'invalidSharingRequest'
}
]
}
Can you please help me to find that folder in google drive using google drive API?

Related

Google Apps Script call Address Validation API

Simple code and straightforward. It works with postman but fails with Apps Script.
function validateAddress () {
const url = 'https://addressvalidation.googleapis.com/v1:validateAddress?key=';
const apikey = '...';
let payload, options, temp;
payload = JSON.stringify({
"address": {
"addressLines": "1600 Amphitheatre Pkwy"
}
});
options = {
'muteHttpExceptions': true,
'method': 'POST',
'Content-Type': 'application/json',
'body': payload
}
temp = UrlFetchApp.fetch(url + apikey, options);
Logger.log(temp)
}
Error:
{
"error": {
"code": 400,
"message": "Address is missing from request.",
"status": "INVALID_ARGUMENT"
}
}
EDIT:
Change options to
options = {
'muteHttpExceptions': true,
'method': 'POST',
'Content-Type': 'application/json',
'payload': payload
}
Gives error:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}\": Cannot bind query parameter. Field '{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}\": Cannot bind query parameter. Field '{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}' could not be found in request message."
}
]
}
]
}
}
Documentation:
https://developers.google.com/maps/documentation/address-validation/requests-validate-address
From the documentation, it seems that addressLines is an array of string, not a string. Does that change something ? (I don't have a key, so I cannot try myself).
And more important, your options object is incorrect (check doc). It should be
options = {
'muteHttpExceptions': true,
'method': 'POST',
'contentType': 'application/json',
'payload': payload
}
I don't know why it works but changed options to
options = {
'muteHttpExceptions': true,
'method': 'POST',
'headers': {
'Content-Type': 'application/json'
},
'payload': payload
}
Solves the problem.

Apps Script projects.deployments.create throwing GaxiosError: Requested entity was not found

I am trying to set up a onEdit trigger for Google SHeets using the Apps Script API.
I have managed to create and update a script project by the code given below (this is working fine)
const createScriptRes = await this.script.projects.create({
requestBody: {
title,
},
})
if (createScriptRes.err) {
responseObj.err = createScriptRes.err
return responseObj
}
const scriptId = createScriptRes.data.scriptId
const updateScriptRes = await this.script.projects.updateContent({
scriptId,
auth: this.auth,
resource: {
files: [
{
name: 'gsheet_trigger',
type: 'SERVER_JS',
source: `
function onEdit(e) {
UrlFetchApp.fetch("http://localhost:3000/webhooks/gsheet", {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify({ rowInd: e.range.getRowIndex() })
})
}
function setup() {
const sheet = SpreadsheetApp.openById("SHEET_ID")
ScriptApp.newTrigger("onEdit").forSpreadsheet(sheet).onEdit().create()
}
`,
},
{
name: 'appsscript',
type: 'JSON',
source: `{"timeZone":"America/New_York","exceptionLogging": "CLOUD", "executionApi": {
"access": "ANYONE"
}}`,
},
],
},
})
Now, I am facing "Requested entity not found" when I try to deploy this script project using the below code.
const deployScriptRes = await this.script.projects.deployments.create({
scriptId,
requestBody: {
versionNumber: 1,
manifestFileName: 'appsscript',
},
})
The full error body is
errors: [
{
message: 'Requested entity was not found.',
domain: 'global',
reason: 'notFound'
}
]
I have looked for the solution on documentation, github issues and StackOverflow, but didn't find anything specific to this
Try changing requestBody to resource and remove extra comma:
const deployScriptRes = await this.script.projects.deployments.create({
scriptId,
resource: {
versionNumber: 1,
manifestFileName: 'appsscript' //remove comma at end
},
})

NuxtJS - Google Auth: ExpiredAuthSessionError: Both token and refresh token have expired. Your request was aborted

Im using nuxtjs for a while. Before my last update all auth feature run smoothly.
But after I update the nuxt.config.js move axios plugin from plugins array to auth config object the error occurred. I need to put axios in auth config object because I need to access $auth from axios plugin.
Version
"#nuxtjs/auth-next": "5.0.0-1607693598.34d83ea"
"nuxt": "^2.15.2"
Nuxt configuration
Mode:
Universal
Nuxt configuration
auth: {
plugins: [{ src: "~/plugins/axios.js", ssr: true }], // <-- I put this, move from plugins array
strategies: {
local: {
token: {
property: "data.token",
required: true,
type: "",
maxAge: 18000,
},
user: {
property: "data",
autoFetch: true,
},
endpoints: {
login: { url: "/api/main", method: "post" },
logout: { url: "/api/profiles/logout", method: "get" },
user: { url: "/api/profile", method: "get" },
},
},
google: {
responseType: "code",
clientId:"<google client ID>",
codeChallengeMethod: "",
grantType: "authorization_code",
redirectUri: `${baseUrl}/verify-auth`,
},
},
redirect: {
login: "/login",
logout: "/login",
callback: "/login",
home: "/",
},
},
Reproduction
ExpiredAuthSessionError: Both token and refresh token have expired. Your request was aborted.
at a5d2e4e.js:1:4374
Steps to reproduce
After selecting a google account, then redirected to /verify-auth, then the error occurred. After /verify-auth it should go in.
Update google auth config like this:
google: {
responseType: "code",
clientId:"<google client ID>",
codeChallengeMethod: "",
grantType: "authorization_code",
redirectUri: `${baseUrl}/verify-auth`,
token: {
property: "data.token", // <-- based on your API response (endpints.login)
required: true,
type: "",
maxAge: 18000,
},
user: {
property: "data",
autoFetch: true,
},
endpoints: {
login: { url: "{your google auth API}", method: "post" }, // <-- should return response with token on it
logout: { url: "/api/profiles/logout", method: "get" },
user: { url: "/api/profile", method: "get" },
},
}

useDomainAdminAccess creates error in Google Drive API using service account authentication

I am creating a service to watch some of my Shared Drive folders on Google Drive. I am using a service account for authentication as this is a service running on a server. Here is my code snippet:
const { google } = require("googleapis");
const auth = new google.auth.GoogleAuth({
keyFile: "./credentials.json",
scopes: ["https://www.googleapis.com/auth/drive"],
});
const drive = google.drive({ version: "v3", auth });
drive.drives
.list({ q: "name = Clients", useDomainAdminAccess: true })
.then((files) => {
console.log(files);
})
.catch((err) => {
console.log(err);
});
If I leave the list method parameters empty, I get back a response with status code 200 and an empty list of drives as expected (as the service account does not own any shared drives). As soon as I add the use useDomainAdminAccess: true parameter, I get an error response as follows:
GaxiosError: Invalid Value
at Gaxios._request (/Users/bteres/Projects/fw-docs/node_modules/gaxios/build/src/gaxios.js:85:23)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async JWT.requestAsync (/Users/bteres/Projects/fw-docs/node_modules/google-auth-library/build/src/auth/oauth2client.js:342:22) {
response: {
config: {
url: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true',
method: 'GET',
userAgentDirectives: [Array],
paramsSerializer: [Function],
headers: [Object],
params: [Object: null prototype],
validateStatus: [Function],
retry: true,
responseType: 'json',
retryConfig: [Object]
},
data: { error: [Object] },
headers: {
'alt-svc': 'h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
'cache-control': 'private, max-age=0',
connection: 'close',
'content-encoding': 'gzip',
'content-security-policy': "frame-ancestors 'self'",
'content-type': 'application/json; charset=UTF-8',
date: 'Sun, 07 Jun 2020 10:43:54 GMT',
expires: 'Sun, 07 Jun 2020 10:43:54 GMT',
server: 'GSE',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block'
},
status: 400,
statusText: 'Bad Request',
request: {
responseURL: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true'
}
},
config: {
url: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true',
method: 'GET',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function],
headers: {
'x-goog-api-client': 'gdcl/4.2.1 gl-node/12.17.0 auth/6.0.1',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/4.2.1 (gzip)',
Authorization: 'REDACTED',
Accept: 'application/json'
},
params: [Object: null prototype] {
q: 'name = Clients',
useDomainAdminAccess: true
},
validateStatus: [Function],
retry: true,
responseType: 'json',
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [Array],
noResponseRetries: 2,
statusCodesToRetry: [Array]
}
},
code: 400,
errors: [
{
domain: 'global',
reason: 'invalid',
message: 'Invalid Value',
locationType: 'parameter',
location: 'q'
}
]
}
I tried leaving that out and only using the q parameter and I get the same response. If I leave out the q parameter, same problem.
I have been at this for a couple of days and any help would be greatly appreciated.
UPDATE:
I have already enabled domain-wide delegation for the service account as can be seen below.
I have also enabled this in my G-Suite admin API Management controls as seen below.
Did I possibly get some of the config incorrect here?
After hours of struggle and another nudge, I managed to figure this out. Google's API documentation is not so clear on this. Basically, you can use your service account but the service account need to impersonate a specific user, it is not by default an admin user in your domain even if you have all the configuration done.
So the easiest option I could figure out was to use google-auth's JWT credentials method as below:
const { google } = require("googleapis");
const credentials = require("./credentials.json");
const scopes = ["https://www.googleapis.com/auth/drive"];
const auth = new google.auth.JWT(
credentials.client_email,
null,
credentials.private_key,
scopes,
"admin#domain.com"
);
const drive = google.drive({ version: "v3", auth });
After changing the auth method to this, the query above works as expected.

Spring + React fetch data

i have a problem with fetch data from api exposed by spring.
I want to fetch data by:
componentDidMount() {
this.setState({isLoading: true});
fetch('http://localhost:8080/api/tasks/')
.then(response => { return response.json() })
.then(results => this.setState({
tasks: results,
isLoading: false
}));
The spring api which return data:
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping
public List<Task> findTasksByUserId() {
return taskService.findTasksBelongToUser(idProvider.getCurrentUserId());
}
Returned JSON:
[
{
id: 1,
version: 0,
name: "Task1",
description: "description1",
priority: 1,
finished: true,
category: {
id: 1,
version: 0,
name: "Uncategorized",
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
}
},
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
},
position: 0
},
{
id: 2,
version: 0,
name: "Task2",
description: "description2",
priority: 4,
finished: true,
category: {
id: 1,
version: 0,
name: "Uncategorized",
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
}
},
user: {
id: 1,
version: 0,
login: "admin",
email: "admin#todo.pl",
enabled: true
},
position: 1
}]
And i got a error like this:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
I dont know what is wrong but maybe format of json is not correct, because it's start with the sign '['.
I am a beginner in React so please about some hint and help.
regards
fetch() returns a promise which gets resolved into an HTTP response of course, not the actual JSON. To extract the JSON body content from the response, we use the json() method.
Try adding two headers Content-Type and Accept to be equal to application/json.
fetch('http://localhost:8080/api/tasks/', {
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(response => { return response.json() })
.then(results => this.setState({
tasks: results,
isLoading: false
}));