0

I'm trying to disable download/print/copy content using the method setViewersCanCopyContent(false) and setWritersCanShare(false) when creating a file with a Service Account, but if I open the file in a browser that I'm not logged in in a Google account, I'm still able to execute those functionalities.

EDIT (added more info)

Here is how I am working: I have this service account and, also, I have what I've called a "service account owner", that is the email I used to create the service account in developer console > IAM. When I call my application, my code creates a folder in service account's Drive and then I move it to my service account owner's Drive and set it as owner (using setTransferOwnership(true)) - I use this approach because, as I could note, service account's Drive is not accessible via browser (only via API).

Then, when I create a file, I call setParents({FOLDER_ID}) where FOLDER_ID is the ID of the folder in service account owner's Drive. Then, when I login service account owner's Drive and select a file, I can see that the service account is the owner of the file and anyone with the link can view file, but everyone that can view the file, can also download/print/copy content.

Here is the code I'm using:

HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
final Credential credential = new GoogleCredential.Builder()                        
    .setTransport(transport)
    .setJsonFactory(jsonFactory)
    .setServiceAccountId({SERVICE_ACCOUNT_ID})
  .setServiceAccountScopesArrays.asList(DriveScopes.DRIVE_METADATA_READONLY, DriveScopes.DRIVE, DriveScopes.DRIVE_FILE, DriveScopes.DRIVE_APPDATA)
    .setServiceAccountPrivateKeyFromP12File(new File("{PATH_TO_P12_FILE}")
    .build();

Drive drive = new Drive.Builder(transport, jsonFactory, credential)
    .setHttpRequestInitializer(new HttpRequestInitializer() {
         @Override
         public void initialize(HttpRequest httpRequest) throws IOException {
             credential.initialize(httpRequest);
             httpRequest.setConnectTimeout(2 * 60000);  // 2 minutes connect timeout
             httpRequest.setReadTimeout(2 * 60000);  // 2 minutes read timeout

         }
    })
    .setApplicationName("{MY_APP}")
    .build();

File fileMetadata = new File();
fileMetadata.setName("test.doc");
fileMetadata.setMimeType("application/vnd.google-apps.document");
fileMetadata.setViewersCanCopyContent(false);
fileMetadata.setWritersCanShare(false);
fileMetadata.setParents(Arrays.asList("{SERVICE_ACCOUNT_OWNER_FOLDER_ID}"));

File file = null;

try {
    FileContent mediaContent = new FileContent("application/vnd.openxmlformats-officedocument.wordprocessingml.document", new java.io.File("{PATH_TO_FILE.doc}"));
    file = this.drive.files()
        .create(fileMetadata, mediaContent)
        .setFields("id, webViewLink")
        .execute();
} catch (IOException e) {
    e.printStackTrace();
}

Permission readPermission = new Permission();
readPermission.setType("anyone");
readPermission.setRole("reader");

drive.getDrive().permissions().create(file.getId(), readPermission)
            .execute();

Is it possible to disable these functionalities with a Service Account?

lucasdc
  • 1,032
  • 2
  • 20
  • 42

3 Answers3

1

I am not sure i completely understand the problem here.

First off a service account is not you. Think of it as a dummy user It only has the access to your account that you have given it. I am going to assume that you shared the folder with the service account.

Now if we look at your code when you are authenticating your service account you are authenticating it with a scope this are the scopes of access.

setServiceAccountScopesArrays.asList(DriveScopes.DRIVE_METADATA_READONLY, DriveScopes.DRIVE, DriveScopes.DRIVE_FILE, DriveScopes.DRIVE_APPDATA)

Adding all of those is pretty much over kill as DriveScopes.Drive gives you full access anyway.

So if you want to prevent the service account from writing to the files then you should only use DriveScopes.DRIVE_METADATA_READONLY

What i dont understand

In my Google Drive, when I select the created file, I can see that I am the owner of the file and anyone with the link can see it. But everyone is able to download/print/copy content of the file.

When you login to the Google drive website logged in as yourself you can create a file and the service account will be able to to see it. But i am not sure what you mean by everyone else. No one can see your personal files in Google drive that you haven't given access to. If you share a file with someone there is no way to prevent them from download/print/copy it. That has nothing to do with a service account.

update:

Then, when I login service account owner's Drive and select a file, I can see that the service account is the owner of the file and anyone with the link can view file, but everyone that can view the file, can also download/print/copy content.

No if you give someone a link to the file and they view it in their google drive there is no way to prevent them from download/print/coping the content

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Thanks for your help. I will replace drive scopes in my code. I've edited my question to make it clear so you can understand what's happening. When you say 'If you share a file with someone there is no way to prevent them from download/print/copy it', you mean that calling setViewersCanCopyContent(false) does not take any effect when I create a file and create a permission with role "reader" and type "anyone"? – lucasdc Aug 30 '17 at 15:54
  • check update. clever way of getting around the lack of web view in a service account. – Linda Lawton - DaImTo Aug 30 '17 at 15:58
  • I've seen your update but I don't agree with "there is no way to prevent them from download/print/coping the content". If I create a file via Google Drive in Sharing dialogue > Advanced > there is an option "Disable options to download, print, and copy for commenters and viewers". If I check it and open this file with another Google account, I am not able to download/print/copy. My question is how to achieve this via code (API). – lucasdc Aug 30 '17 at 16:16
  • Again to my knowledge it is not I have only been working with this for five years. If you don't trust me i can try and ping someone on the team for verification. – Linda Lawton - DaImTo Aug 30 '17 at 16:18
  • Ok.. I trust you, but that makes me wonder why would Google create those methods if that is not applicable – lucasdc Aug 30 '17 at 16:25
  • 1
    Its probably something built in on drive there are a number of google only features. Wait for my contact to respond worse case we add a feature request. I have looked for this feature before. Best case its hidden someplace in the documentation that neither one of us has spotted. – Linda Lawton - DaImTo Aug 30 '17 at 16:35
  • Any news @DaImTo? – lucasdc Sep 05 '17 at 18:11
  • my google contact suggested this should work File.viewersCanCopyContent: https://developers.google.com/drive/v3/reference/files#viewersCanCopyContent I haven't had time to test it myself. – Linda Lawton - DaImTo Sep 20 '17 at 14:23
0

You're doing it the correct way. fileMetadata.setViewersCanCopyContent(false); is how you should be able to prevent downloads. I'm wondering if somehow this is being lost during the transferOwnership.

If you want your file to be owned by a regular account (your "service account owner"), then you will find it much simpler to just create the file directly under that account, rather than go through the extra steps of first creating it under a Service Account and then transferring it. It will clean your code up and also avoid any subtle side-effects of the transfer process.

pinoyyid
  • 21,499
  • 14
  • 64
  • 115
  • I'm transfering ownership only on the folder, not on files, that means that all files are owned by my service account. I'm not able to create a file under the "service account owner" because I'm not using G Suite and I am not able to impersonate an user email. – lucasdc Aug 31 '17 at 13:51
  • you are able to create files on service account owner using a stored Refresh Token. See https://stackoverflow.com/questions/19766912/how-do-i-authorise-an-app-web-or-installed-without-user-intervention-canonic – pinoyyid Aug 31 '17 at 14:49
  • Yes, but this approach runs out of my scope. One of the requirements is to use a service account to create files. – lucasdc Sep 01 '17 at 11:19
0

I noted that if I update file like this (after creation):

File updatedFile = new  File();
updatedFile.setViewersCanCopyContent(false);
updatedFile.setWritersCanShare(false);
drive.files().update(file.getId(), updatedFile).execute();

Then it disables download/print/copy. I am still not able disable it on file creation, but this way is enough for my requirements.

lucasdc
  • 1,032
  • 2
  • 20
  • 42