With a Google Suite Business plan, I need to get a file from some user and copy it to Team Drive folder owned by ANOTHER user through a Service Account properlly authorized by Domain-Wide-Delegation.
My approach: considering that Service Account has the power to access users data, change the permission of the user's file to allow the whole domain to read it, copy it to a folder inside the Team Drive owned by another user and then setting the owner of Team Drive as the owner of the copied file.
The following code is always returning File not found for the first Google Drive request (change the permission). I guarantee that the file really exists in user's folder.
const fs = require('fs');
const path = require('path');
const google = require('googleapis');
fs.readFile('/path/to/my/service/account/credentials', (readError, serviceAccountData) => {
/**
serviceAccountData is an object:
{
"type": "service_account",
"project_id": "__",
"private_key_id": "__",
"private_key": "__",
"client_email": "__@__.iam.gserviceaccount.com",
"client_id": "__",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/___.iam.gserviceaccount.com"
}
*/
if (readError) {
console.log(readError);
} else {
let serviceAccount = null;
try {
serviceAccount = JSON.parse(serviceAccountData);
} catch (parseError) {
console.log(parseError);
return;
}
const jwtClient = new google.auth.JWT(serviceAccount.client_email, null, serviceAccount.private_key, SCOPES, null, 'lordshark@example.com');
jwtClient.authorize((authorizeError, tokens) => {
if (authorizeError) {
console.log(authorizeError);
} else {
// ID of any file that belongs to lordshark@example.com
// This file is stored in lordshark@example.com Google Drive (user space)
let sourceFileId = '____';
// ID of a folder in a Team Drive OWNED BY A DIFFERENT user that isn't lordshark@example.com
// lordshark@example.com DOES NOT HAVE access to this Team Drive
let teamDriveFolderId = '____'/
const googleDrive = google.drive({
version: 'v3',
auth: jwtClient
});
googleDrive.permissions.create({
fileId: sourceFileId,
useDomainAdminAccess: true,
resource: {
role: 'reader',
type: 'domain',
domain: 'example.com',
}
}, (createPermissionError, permissionResponse) => {
if (createPermissionError) {
console.log(createPermissionError);
} else {
googleDrive.files.copy({
fileId: sourceFileId,
supportsTeamDrives: true,
ignoreDefaultVisibility: true,
resource: {
description: 'Copy of a file from user to store in Team Driver',
parents: [teamDriveFolderId]
}
}, (copyError, copyResponse) => {
if (copyError) {
console.log(copyError);
} else {
googleDrive.permissions.create({
fileId: copyResponse.id,
transferOwnership: true,
resource: {
role: 'owner',
type: 'user',
emailAddress: administrator
}
}, (ownerPermissionError, ownerPermissionResponse) => {
if (ownerPermissionError) {
console.log(ownerPermissionError);
} else {
console.log(ownerPermissionResponse);
}
});
}
});
}
});
}
});
}
});
The stacktrace:
{ Error: File not found: 1K-dQt5uwfUc331uKc2vxUn3MP3nohLPZ. at Request._callback (node_modules\googleapis\node_modules\google-auth-library\lib\transporters.js:85:15) at Request.self.callback (node_modules\request\request.js:186:22) at emitTwo (events.js:106:13) at Request.emit (events.js:191:7) at Request. (node_modules\request\request.js:1163:10) at emitOne (events.js:96:13) at Request.emit (events.js:188:7) at IncomingMessage. (node_modules\request\request.js:1085:12) at IncomingMessage.g (events.js:292:16) at emitNone (events.js:91:20) code: 404, errors: [ { domain: 'global', reason: 'notFound', message: 'File not found: 1K-dQt5uwfUc331uKc2vxUn3MP3nohLPZ.', locationType: 'parameter', location: 'fileId' } ] }