0

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' } ] }

lordshark
  • 83
  • 9
  • I already tried with and without `lordshark@example.com`, `useDomainAdminAccess: true` and the error keeps the same. – lordshark Feb 09 '18 at 16:57
  • Refactor that code, it is completely unreadable. I lost myself in the third if-else. – Ivan Beldad Feb 09 '18 at 17:26
  • Sorry, Ivan. First I write 'sausage-fast-codes' for a proof of concept to understand these Google API's. I try to handle all possibles... so the amount of if's and try's instead of creating many functions. It's the callback-hell of JS. It will take me time to rewrite... but I'll make an effort. – lordshark Feb 09 '18 at 17:34
  • Can you give the Drive API [files.list try-it](https://developers.google.com/drive/v3/reference/files/list#try-it) a try if you're able to get a positive result? – ReyAnthonyRenacia Feb 10 '18 at 10:28
  • Thanks for your suggestion, noogui. I really tried this but no success. Always returning empty results... `{ kind: 'drive#fileList', incompleteSearch: false, files: [] }` and I tried many different queries. – lordshark Feb 14 '18 at 12:30
  • I also tried with OAuth2 credentials, generating tokens and so on... and in this case I got success listing files. But only for the user with the authorization consent. – lordshark Feb 14 '18 at 12:40
  • 1
    https://github.com/google/google-auth-library-nodejs/blob/b6db93a5c5d66154914e86a01539b6cacdfb9a45/src/auth/jwtclient.ts#L59 Do you have the same parameters? I think the null after scopes is wrong. – Derek Kite Feb 18 '18 at 17:38
  • @lordshark were you able to find a solution? I am able to list files, etc... from a service account but am running into an authorization probelm when trying to update permissions on a team drive, with and without the useAdminstratorAccess. – FantasticSponge Dec 04 '18 at 14:34
  • Sorry @FantasticSponge. I did not find a solution. I stopped this project and decided to go into another way. Maybe in the future I'll need this scenario again... – lordshark Dec 28 '18 at 21:18

0 Answers0