Search code examples
pythongoogle-cloud-platformgoogle-sheets-apigoogle-docs-apiservice-accounts

GCP Sheets/Docs API not displaying files in iframe


I have a project that every time a new object is saved it also creates blank Google Doc and Google Sheet as additional resources users can work with.

For that I created a Service Account inside Google Cloud Platform, generated the .json, granted the permissions said in the documentation (Browser, Service Account Admin, IAM Workload Identity Pool Admin, Workload Identity User).

Also created an API Key.

With that I can successfully create, delete, list all files and rename particular file (scripts below) but I cannot load the iframe with the document and the spreadsheet itself. The address I tried to load in the iframe's src:

https://docs.google.com/document/d/DOC_ID?key=APIKEY

https://docs.google.com/spreadsheets/d/SHEET_ID/?key=APIKEY

https://docs.googleapis.com/v1/documents/DOC_ID?key=APIKEY

https://sheets.googleapis.com/v4/spreadsheets/SHEET_ID?key=APIKEY

First two address loads the "You need access - Ask for access, or switch to an account with access." Google message (screenshot here "You need access" issue).

The other two throws 401 - "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.".

Questions:

  1. How can I display these files on Google's standard iframe (with the user interface, toolbar, etc.)?

  2. Is there a way to see all files created by the service account in the Google Cloud Platform website like a personal Google Drive allows? I tried drive.google.com and it's empty, but I can list them all using Python.

  3. I tried to make it work with Workload Identity Federation in AWS so I created the Pool, set AWS as the Provider with my AWS ID and selected the Service Account from the "CONNECTED SERVICE ACCOUNTS". Is there a guide about the AWS configuration side for this? I put it aside for now because I don't know the next step.

# GOOGLE DOC CREATION
def document_create(request, obj):

    SERVICE_ACCOUNT_FILE = '.json'
    SCOPES = ['https://www.googleapis.com/auth/documents']
    body = {
        'title': obj.title,
    }
    creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    service = build('docs', 'v1', credentials=creds)
    document = service.documents().create(body=body).execute()
# GOOGLE SHEET CREATION
def spreadsheet_create(request, obj):

    SERVICE_ACCOUNT_FILE = '.json'
    SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
    spreadsheet = {
        'properties': {
            'title': obj.title,
        }
    }
    creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    service = build('sheets', 'v4', credentials=creds)
    spreadsheet = service.spreadsheets().create(body=spreadsheet, fields='spreadsheetId').execute()
# LIST ALL FILES
def index(request, template='gcp/index.html'):
    
    SERVICE_ACCOUNT_FILE = '.json'
    SCOPES = [] # WORKS WITHOUT ANY SCOPE SOMEHOW
    creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    service = build('drive', 'v3', credentials=creds)
    
    results = service.files().list().execute()
    drive_list = results.get('files', [])
# RENAME A FILE
def rename(request):

    SERVICE_ACCOUNT_FILE = '.json'
    SCOPES = [] # ALSO WORKS WITHOUT ANY SCOPE SOMEHOW
    creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    service = build('drive', 'v3', credentials=creds)
    
    try:
        service.files().update(fileId=file_id, body={'name': new_file_name}).execute()
    except Exception as e:
        pass

(It's my first post here, so apologies if something is not how it's supposed to be.)

Thanks in advance!


Solution

  • Turns out every new file created using Sheets and Docs API is private by default.

    To make it available you just need to add new permissions specifying type (user/domain), role, and the value corresponding to the type selected.

    This must be done using Drive API.