背景
社内で使用されている、Google Drive のドキュメントで、共有設定が「リンクを知っている全員が編集可」になっているファイルが無いか確認する必要がありました。
GSuiteの管理コンソールから「レポート」->「セキュリティ」で、外部とリンク共有中のファイルを下記方法で確認できます。
しかし、レポートの内容では「誰が」「外部リンク中のファイルを何個もっているか」しか表示されません。
Google API を利用して取得したファイルをスプレッドシートにリストする方法を記載します。
「Admin SDK」を有効にする方法はこちらを参照してください。
- 有効にするAPI
- Google Drive API
- Google Sheets API
コードの仕様
- 誰でもアクセスできるファイルをスプレッドシートにリスト保存する
- 画像や動画は対象に含めない
- 最終更新日から100日を超えているものは、共有範囲をドメイン内に設定する
- 何かしらの理由で権限を取得できなかった場合は、別リストに保存する
実際のコード
list.py
# -*- coding: utf-8 -*-
from __future__ import print_function
import httplib2
import sys, os, time
from datetime import *
from apiclient import discovery
from apiclient import errors
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
CLIENT_SECRET_FILE = 'hoge.json'
CREDENTIAL_FILE = 'fuga.json'
APPLICATION_NAME = 'Drive Get Public Files'
SCOPES = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets'
SPREADSHEET_ID = '保存するスプレッドシートのID'
"""
有効な証明書をストレージから取得
"""
def get_credentials():
#認証情報を格納するディレクトリの作成
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
#OSにパスを通す
credential_path = os.path.join(credential_dir, CREDENTIAL_FILE)
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
#認証処理を行うクラスのインスタンスを生成
flow = client.flow_from_clientsecrets(
os.path.join(home_dir, '.credentials', 'client_secrets', CLIENT_SECRET_FILE), SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Python 2.6 互換用処理
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
discovery_url = ('https://sheets.googleapis.com/$discovery/rest?' 'version=v4')
drive_service = discovery.build('drive', 'v3', http=http)
# スプレットシートサービスオブジェクトのビルド
ss_service = discovery.build('sheets', 'v4', http=http, discoveryServiceUrl=discovery_url)
page_token = None
public_permissions = []
unknown_permissions = []
putblic_last_row = 2
unknown_last_row = 2
now_datetime = datetime.now()
while True:
response = drive_service.files().list(
q="mimeType!='application/vnd.google-apps.folder' and mimeType!='image/jpeg' and mimeType!='video/quicktime' ",
spaces='drive',
fields='nextPageToken, files(id, name, webViewLink, modifiedTime)',
pageToken=page_token
).execute()
for file in response.get('files', []):
try:
file_id = file.get('id', None)
memo = '' #備考
# ファイルの権限を取得
permissions = drive_service.permissions().list(fileId=file_id).execute()
permission_items = permissions.get('permissions', [])
# ドキュメントに設定されている権限リストをループする
for item in permission_items:
permission_id = item.get('id', '')
permission_type = item.get('type', '')
# 誰でもアクセスできる場合、配列に保存
if (permission_id == 'anyoneWithLink'):
# 最終更新日が3ヶ月以上前の場合は、共有設定を変更
last_update_str = file.get('modifiedTime', None)
last_update_datetime = datetime.strptime(last_update_str[:-1], '%Y-%m-%dT%H:%M:%S.%f')
diff_hour = (now_datetime - last_update_datetime).total_seconds() / (3600 * 24)
if(diff_hour > 100):
print('100日より前です')
# 誰でもアクセスできる権限を削除
drive_service.permissions().delete(fileId=file_id, permissionId='anyoneWithLink').execute()
# ドメインメンバーがアクセスできる権限を追加
batch = drive_service.new_batch_http_request(callback=callback)
batch.add(drive_service.permissions().create(
fileId=file_id,
body={
'role': 'writer',
'type': 'domain',
'allowFileDiscovery': False,
'domain': 'aaaaa.jp',
'kind': 'drive#permission'
},
fields='id'
))
batch.execute()
memo = '100日経過したので共有設定しなおしました'
# 配列に保存
public_permissions.append([file.get('webViewLink', None), file.get('name', None), memo])
print('#', end='', flush=True)
# 10個ごとにシートに反映する
if((len(public_permissions) > 0) and (len(public_permissions) % 10 == 0)):
# ワークシート情報を設定
range_name = 'file list' + '!A' + str(putblic_last_row)
body = {'values': public_permissions}
print('シートに反映')
result = ss_service.spreadsheets().values().update(
spreadsheetId=SPREADSHEET_ID,
range=range_name, valueInputOption='USER_ENTERED', body=body).execute()
public_permissions = []
putblic_last_row += 10
# 使用中もしくは読み込めずにエラーになった場合
except:
unknown_permissions.append([file.get('webViewLink', None), file.get('name', None)])
print('%', end='', flush=True)
# 10個ごとにシートに反映する
if((len(unknown_permissions) > 0) and (len(unknown_permissions) % 10 == 0)):
range_name = 'file list' + '!E' + str(unknown_last_row)
body = {'values': unknown_permissions}
print('シートに反映')
result = ss_service.spreadsheets().values().update(
spreadsheetId=SPREADSHEET_ID,
range=range_name, valueInputOption='USER_ENTERED', body=body).execute()
unknown_permissions = []
unknown_last_row += 10
continue
page_token = response.get('nextPageToken', None)
if page_token is None:
break;
def callback(request_id, response, exception):
if exception:
# Handle error
print(exception)
else:
print("Permission Id: %s" % response.get('id'))
if __name__ == '__main__':
main()