Google API file permissions using python

泪湿孤枕 提交于 2020-05-16 23:00:12

问题


I need to do some functionality for different users of my site to automatically upload html files to google disk and open them for viewing and editing in google docs. To do this I create a document, pass it to google disk and use the id of the created document to open it in google docs.
To access api, I use a json file taken from the service Google account. I tried to execute my code with owner and view rights, but the result is the same.

class CvView(AuthorizedMixin, View):
    """Here I check if the file format is html, I temporarily save it on disk and pass it to the file_to_drive function (to save it to google disk and open it in google docs) and delete it from disk"""


    def get(self, request, employee_id, format_):
        """Returns employee's CV in format which is equal to `format_`
        parameter."""

        employee = get_object_or_404(Employee, pk=employee_id)
        user = request.user
        content_type, data = Cv(employee, format_, user).get()

        if isinstance(data, BytesIO):
            return FileResponse(
                data, as_attachment=True, filename=f'cv.{format_}',
                content_type=content_type)
        if content_type == 'text/html':
            try:
                name = uuid.uuid4().hex + '.html'
                with open(name, 'w+') as output:
                    output.write(str(data))
                return HttpResponseRedirect(file_to_drive(import_file=name))
            finally:
                os.remove(os.path.join(settings.BASE_DIR, name))
        return HttpResponse(data, content_type=content_type)

file_to_drive

from google.oauth2 import service_account
from django.conf import settings
from googleapiclient.discovery import build

SCOPES = [
    'https://www.googleapis.com/auth/documents',
    'https://www.googleapis.com/auth/drive',
]
ACCOUNT_FILE = os.path.join(settings.BASE_DIR, 'cv-base-gapi.json')
def file_to_drive(import_file=None):
    credentials=service_account.Credentials.from_service_account_file(ACCOUNT_FILE, scopes=SCOPES)
    service = build('drive', 'v3', credentials=credentials)
    file_metadata = {
        'name': 'My Report',
        'mimeType': 'application/vnd.google-apps.spreadsheet'
    }
    media = MediaFileUpload(import_file,
                            mimetype='text/html',
                            resumable=True)
    file = service.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
    print('File ID: %s' % file.get('id'))
    return (f"https://docs.google.com/document/d/{file.get('id')}/edit")

And it seems to be working, but there's an unclear moment.

First of all, I don't see the saved file on the Google disk, but the print('File ID: %s' % file.get('id')) line gives me the id of the new document.

And the second most important problem is that I get a message about the missing permissions to view the document.


回答1:


  • You want to create new Google Document from HTML data.
  • You want to make users view and edit the created Google Document.
  • You are using the service account for this situation.
  • You want to achieve this using google-api-python-client with Python.

I could understand about your situation like above. And your question has 2 questions.

  1. You want to know the reason that the created Google Document cannot be seen at your Google Drive.
  2. You want to know the reason that the permissions is required to be opening the created Document.

If my understanding is correct, how about this answer? Please think of this as just one of several answers.

Issue:

As the main reason of your both questions, I think the use of the service account is the reason. The service account is different from your own Google account. So for example, when the file is created by the service account, the file is created in the Google Drive of the service account. By this, the file cannot be seen at your Google Drive. I think that this is the answer of your question 1. And, the file created in the Google Drive of the service account cannot be directly accessed because only the service account can access to it. I think that this is the answer of your question 2.

Solution:

In order to see the created Google Document on your Google Drive and make users view and edit the created Google Document, I would like to propose to add the permissions to the created Google Document using Permissions: create in Drive API. When this is reflected to your script, it becomes as follows.

Modified script:

Please modify your script as follows.

From:
def file_to_drive(import_file=None):
    credentials=service_account.Credentials.from_service_account_file(ACCOUNT_FILE, scopes=SCOPES)
    service = build('drive', 'v3', credentials=credentials)
    file_metadata = {
        'name': 'My Report',
        'mimeType': 'application/vnd.google-apps.spreadsheet'
    }
    media = MediaFileUpload(import_file,
                            mimetype='text/html',
                            resumable=True)
    file = service.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
    print('File ID: %s' % file.get('id'))
    return (f"https://docs.google.com/document/d/{file.get('id')}/edit")
To:
def file_to_drive(import_file=None):
    credentials=service_account.Credentials.from_service_account_file(ACCOUNT_FILE, scopes=SCOPES)
    service = build('drive', 'v3', credentials=credentials)
    file_metadata = {
        'name': 'My Report',
        'mimeType': 'application/vnd.google-apps.document'  # Modified
    }
    media = MediaFileUpload(import_file,
                            mimetype='text/html',
                            resumable=True)
    file = service.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
    fileId = file.get('id')  # Added
    print('File ID: %s' % fileId)

    # --- I added below script.
    permission1 = {
        'type': 'user',
        'role': 'writer',
        'emailAddress': '###',  # Please set your email of Google account.
    }
    service.permissions().create(fileId=fileId, body=permission1).execute()
    permission2 = {
        'type': 'anyone',
        'role': 'writer',
    }
    service.permissions().create(fileId=fileId, body=permission2).execute()
    # ---

    return (f"https://docs.google.com/document/d/{file.get('id')}/edit")
  • In this modification, after the Google Document is created, the permissions are added to the created Document.
    • At permission1, your account is added as the writer. By this, you can see the created Document at your Google Drive. Please set your email of Google account here.
    • At permission2, in order to make users view and edit the created Document, the permission is added as anyone type. This is a test case. If you want to add the user's emails as the permissions, please set them like permission1.

Note:

  • When you want to create Google Document, please modify application/vnd.google-apps.spreadsheet to application/vnd.google-apps.document. But in your case, when text/html is converted to application/vnd.google-apps.spreadsheet, it automatically converts to application/vnd.google-apps.document. Because text/html can be converted to only application/vnd.google-apps.document.

Reference:

  • Permissions: create

If I misunderstood your question and this was not the direction you want, I apologize.



来源:https://stackoverflow.com/questions/58080962/google-api-file-permissions-using-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!