Updating Google Drive Metadata with googleapiclient in python - google-api

I am trying to update a Test file's metadata (specifically the file's name) in Google Drive using python's Google API client library. I have used the following google resources:
https://developers.google.com/drive/api/v3/reference/files/update
I haven't had had trouble connecting to googles drive API. I am merely having issues updating the filename or any other metadata that I would want to update.
My code is below:
from googleapiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
from googleapiclient import errors
from googleapiclient.http import MediaFileUpload
# This is to connect to Google Drive's API
SCOPES = 'https://www.googleapis.com/auth/drive.metadata' # drive.metadata gives me the access to read and writeover metadata
CLIENT_SECRET = 'client_id.json' # this is from Oauth when you create credentials for a good project
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET, SCOPES)
creds = tools.run_flow(flow, store)
DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http()))
files = DRIVE.files().list().execute().get('files', [])
print()
print("File Specific metadata")
for f in files:
if f['name']=='Test' and f['mimeType']=='application/vnd.google-apps.document':
print(f['name'], f['id'], f['mimeType'])
file_id = f['id']
print(file_id)
# First retrieve the file from the API.
print()
file = DRIVE.files().get(fileId=file_id).execute()
print(file)
file['name'] = 'A'
print(file)
# Send the request to the API.
updated_file = DRIVE.files().update(fileId=file_id, body=file).execute()
But when I do this, I get an insufficient permissions error. I think it has something to do with the SCOPES but I am not sure.

Related

errors when trying to tweet using tweepy

I am working on an academic research project and I am trying to send out tweets using the the Twitter API. The error I am receiving repeatedly is
Forbidden: 403 Forbidden
Your client app is not configured with the appropriate oauth1 app permissions for this endpoint.
import tweepy
#from tweepy import OAuthHandler
ACCESS_KEY = 'xxx'
ACCESS_SECRET = 'xxx'
CONSUMER_KEY = 'xxx'
CONSUMER_SECRET = 'xxx'
api = tweepy.Client(bearer_token='xxx',
access_token=ACCESS_KEY,
access_token_secret=ACCESS_SECRET,
consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET)
api.create_tweet(text='I want to Tweet')
Here is my code. The authentication raises no errors. Just the attempt at tweeting.
You can fix the problem by activating Read / Write in the Oauth section of your application, and then you shall regenerate the "Access Token and Secret".
You can check that are properly recreated when you see:
Created with Read and Write permissions
EDIT as of 10/February/2023: You are now required to ask for Elevated access if you want to have read + write permission. You only have read access from the V2 API Endpoints as of today

Adding member to a Google group using Google API

I'm trying to add email ids to a Google group using google APIs and Python3. I need help, figuring out what scopes it needs since I am getting the error:
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.
My code:
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']
def main():
"""Shows basic usage of the Admin SDK Directory API.
Prints the emails and names of the first 10 users in the domain.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
print(creds)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'client_secrets.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
service = build('admin', 'directory_v1', credentials=creds)
group_result = service.groups().insert(body={
'groupKey': 'with-automated-addition-of-members#googlegroups.com', # group key
'email': 'sumukhrajubhat2701#gmail.com' # user email who need to insert in google groups
}).execute()
print(group_result)
Anyone please help me with the issue.
You can always check the docs for each method to see what scope it requires. In your case
groups.insert requires one of the following scopes.

Can I limit the available scopes on a Google API service account?

I have done the following:
Created a project in Google API console
Enabled the Google Drive API in the project
Created a service account
Shared a Google Drive folder with the service account
Connected successfully to Google Drive and retrieved the list of folders and files shared with the service account.
When you create an OAuth client ID, you can limit that to predefined scopes. As far as I can tell, the service account has access to any Google Drive scope. I wanted to tighten that down to the following scope: https://www.googleapis.com/auth/drive.readonly just as a reassurance that there's no way the Google Drive app I'm making unintentionally adds/edits/deletes any files.
I know I can add the account to different roles. However, I looked through the list multiple times and none of them are related to Google Drive. I attempted to make my own role, but the available permissions on that screen do not reference Google Drive either. It's possible I missed something or there's another place I could look. Any suggestions?
To limit the scope a Service Account, you have to specify the scope on the server-side.
Service accounts are special Google accounts that can be used by
applications to access Google APIs programmatically via OAuth 2.0. A
service account uses an OAuth 2.0 flow that does not require human
authorization. Instead, it uses a key file that only your application
can access.
For example:
In python, you can specify the scope of a service account by creating a list of scopes and use it as parameter when getting the credentials.
Folder and Files:
python:
Search all image with jpeg extension:
import httplib2
import os
from apiclient import discovery
from google.oauth2 import service_account
scopes = ["https://www.googleapis.com/auth/drive.readonly"]
secret_file = os.path.join(os.getcwd(), 'client_secret.json')
credentials = service_account.Credentials.from_service_account_file(secret_file, scopes=scopes)
service = discovery.build('drive', 'v3', credentials=credentials)
page_token = None
while True:
response = service.files().list(q="mimeType='image/jpeg'",
spaces='drive',
fields='nextPageToken, files(id, name)',
pageToken=page_token).execute()
for file in response.get('files', []):
# Process change
print('Found file: %s' % (file.get('name')))
page_token = response.get('nextPageToken', None)
if page_token is None:
break
Output:
Found file: cute-puppy.jpg
Creating folder with readonly scope:
import httplib2
import os
from apiclient import discovery
from google.oauth2 import service_account
scopes = ["https://www.googleapis.com/auth/drive.readonly"]
secret_file = os.path.join(os.getcwd(), 'client_secret.json')
credentials = service_account.Credentials.from_service_account_file(secret_file, scopes=scopes)
service = discovery.build('drive', 'v3', credentials=credentials)
file_metadata = {
'name': 'Invoices',
'mimeType': 'application/vnd.google-apps.folder'
}
file = service.files().create(body=file_metadata,
fields='id').execute()
Error message:
<HttpError 403 when requesting https://www.googleapis.com/drive/v3/files?fields=id&alt=json returned "Insufficient Permission: Request had insufficient authentication scopes.". Details: "Insufficient Permission: Request had insufficient authentication scopes.">
References:
Google Auth Python
OAuth Scopes

Any alternatives to the "connection" string when using azure storage python client library?

I am about to write my first python program to read/write remote azure storage blob (block blob).
I did some research. It is as if the storage "connection string" is absolutely mandatory. In another word, the Microsoft client-side python library requires a "connection-string" created by the storage account in order to gain access to the remote blob.
In order to keep everything as simple as possible, I am hoping that I can write a small python code to invoke an HTTP GET/PUT method (for accessing the remote azure blob storage resource) without touching the "connection string" generated by the storage account. Yet, it doesn't seem to be possible after reading Microsoft storage documentation.
Can anyone make any comment to shed any light? Thanks in advance.
SAS token is generated by account_name and account_key. Both them are in the connection string too.
With SAS token:
from datetime import datetime, timedelta
from azure.storage.blob import BlobServiceClient, generate_account_sas, ResourceTypes, AccountSasPermissions
sas_token = generate_account_sas(
account_name="<storage-account-name>",
account_key="<account-access-key>",
resource_types=ResourceTypes(service=True),
permission=AccountSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(hours=1)
)
blob_service_client = BlobServiceClient(account_url="https://<my_account_name>.blob.core.windows.net", credential=sas_token)
So you could access with Azure AD Access token based on service principal.
With Azure AD Access token:
from azure.common.credentials import ServicePrincipalCredentials
from azure.storage.blob import BlockBlobService
from azure.storage.common import TokenCredential
TENANT_ID = "xxxxxx"
CLIENT_ID = "xxxxxx"
CLIENT_SECRET = "xxxxxx"
RESOURCE = "https://storage.azure.com/"
credentials = ServicePrincipalCredentials(
client_id = CLIENT_ID,
secret = CLIENT_SECRET,
tenant = TENANT_ID,
resource = RESOURCE
)
token_credential = TokenCredential(credentials.token["access_token"])
ACCOUNT_NAME = "pamelastorage123"
CONTAINER_NAME = "pamelac"
blobService = BlockBlobService(account_name=ACCOUNT_NAME, token_credential=token_credential)
blob = blobService.get_blob_to_text(CONTAINER_NAME, "test.txt")
print(blob.content)
Note: plz follow these steps to assign Storage Blob Data Contributor role and register an application first.
For more information about authentication, see here.

Yahoo Fantasy Sports API Oauth Verifier Not Available

I'm trying to create a program in Python that uses data from Yahoo Fantasy Sports API (Football to be specific). I've already registered an desktop app on the Yahoo Developer Network in order to get permission to use OAuth. I've also gotten the correct urls, client key, and client secret and other necessary information to run the program.
Currently, I am using this website as a resource: https://requests-oauthlib.readthedocs.org/en/latest/oauth1_workflow.html
I managed to complete the get request token phase **, but am now stuck at the **authorization phase, requiring me to get an oauth token and oauth verifier i believe.
However, I'm only able to receive an oauth token, and the methods I call do not return an oauth verifier at all, making it impossible to proceed to the access token step. I'm just looking for some possibilities as to why this is the case.
Thanks.
import csv
import requests
import sys
import time
import webbrowser
from oauth_hook import OAuthHook
from requests_oauthlib import OAuth1Session
from requests_oauthlib import OAuth1
from urlparse import parse_qs
access_token_url = "https://api.login.yahoo.com/oauth/v2/get_token"
request_token_url = "https://api.login.yahoo.com/oauth/v2/get_request_token"
base_authorization_url = "https://api.login.yahoo.com/oauth/v2/request_auth"
callback_URL = "auto-manager.com"
client_key = ".." #can't reveal actual client stuff here
client_secret = ".."
#get request token
oauth = OAuth1Session(client_key,client_secret=client_secret)
print oauth
fetch_response = oauth.fetch_request_token(request_token_url)
resource_owner_key = fetch_response.get('oauth_token')
resource_owner_secret = fetch_response.get('oauth_token_secret')
print fetch_response
print resource_owner_key
print resource_owner_secret
# get authorization, returns no verifier but returns a token for some reason, PROBLEM's here
authorization_url = oauth.authorization_url(base_authorization_url)
print 'please go here and authorize,', authorization_url
redirect_response = raw_input('Paste full redirect URL here: ')
oauth_response = oauth.parse_authorization_response(redirect_response)
print oauth_response
The main issue i've found with requets_oauthlib is that it doesn't let you kind of customize stuff such as headers and body content. I've tried to use it for Yahoo OAuth but i got stuck because of that.
I turned to rauth, with which i managed to make things work. I even developed a special OAuth Lib for Yahoo which supports OAuth1 and OAuth2.
The lib is named yahoo-oauth.
Hope it will help you out.
Have a good one

Resources