背景介绍
谷歌企业账户能不能通过相应的API管理了?如何实现账户回收及数据迁移了?
谷歌提供了一套名为 Workspace Admin SDK 的API管理接口,笔者使用的python,下面一起来看看如何通过这个接口实现账户回收及数据迁移吧。
SCOPES授权请参照此篇文章:https://zhuanlan.zhihu.com/p/567568321
系统环境
- WIN11
- Python 3.10
库安装
pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib
代码部分
用户管理
class UserManageApiRequest(object):
def __init__(self):
# 此处为密钥文件路径
SERVICE_ACCOUNT_FILE = "****.json"
# 鉴权地址,根据操作定义
SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']
try:
# 授权空间(scope)和授权秘钥
self.credential = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
# 授权的账户
self.credentials = self.credential.with_subject('accountapi@gmail.com')
# 接口权限目录
self.service = build("admin", "directory_v1", credentials=self.credentials)
self.result = True
except Exception as err:
self.result = err
def get_user_data(self, user_email: str) -> dict:
results = dict()
try:
results[user_email] = self.service.users().get(userKey=user_email).execute()
except Exception as err:
results[user_email] = err
return results
def delete_user(self, user_email: str):
try:
results = self.service.users().delete(userKey=user_email).execute()
except Exception as err:
print('{} 删除失败'.format(user_email))
raise err
else:
return results
用户数据管理
class UserDataManage(object):
def __init__(self):
SERVICE_ACCOUNT_FILE = "****.json"
SCOPES = ['https://www.googleapis.com/auth/admin.datatransfer']
try:
self.credential = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
self.credentials = self.credential.with_subject('accountapi@gmail.com')
self.service = build('admin', 'datatransfer_v1', credentials=self.credentials)
self.result = True
except Exception as err:
print(err)
self.result = err
def get_applications_info(self) -> dict:
try:
results = self.service.applications().list().execute()
self.service.close()
except Exception as err:
raise err
else:
return results
def user_data_migration(self, new_user_id: str, old_user_id: str, operation: str) -> dict:
try:
Drive_and_Docs = {
"applicationDataTransfers": [
{
"applicationId": '55656082996',
"applicationTransferParams": [
{
"key": "PRIVACY_LEVEL",
"value": ['PRIVATE', 'SHARED'],
},
],
},
],
"kind": "admin#datatransfer#DataTransfer",
"newOwnerUserId": new_user_id,
"oldOwnerUserId": old_user_id,
}
Currents = {
"applicationDataTransfers": [
{
"applicationId": '553547912911',
"applicationTransferParams": [],
}
],
"kind": "admin#datatransfer#DataTransfer",
"newOwnerUserId": new_user_id,
"oldOwnerUserId": old_user_id,
}
Google_Data_Studio = {
"applicationDataTransfers": [
{
"applicationId": '810260081642',
"applicationTransferParams": [
{
"key": "PRIVACY_LEVEL",
"value": ['PRIVATE', 'SHARED'],
},
],
},
],
"kind": "admin#datatransfer#DataTransfer",
"newOwnerUserId": new_user_id,
"oldOwnerUserId": old_user_id,
}
Calendar = {
"applicationDataTransfers": [
{
"applicationId": '435070579839',
"applicationTransferParams": [
{
'key': 'RELEASE_RESOURCES',
'value': ['TRUE'],
},
],
},
],
"kind": "admin#datatransfer#DataTransfer",
"newOwnerUserId": new_user_id,
"oldOwnerUserId": old_user_id,
}
if operation == 'migration_Drive_and_Docs':
results = self.service.transfers().insert(body=Drive_and_Docs).execute()
elif operation == 'migration_Currents':
results = self.service.transfers().insert(body=Currents).execute()
elif operation == 'migration_Google_Data_Studio':
results = self.service.transfers().insert(body=Google_Data_Studio).execute()
elif operation == 'migration_Calendar':
results = self.service.transfers().insert(body=Calendar).execute()
else:
results = 'operation is migration_Drive_and_Docs migration_Currents migration_Google_Data_Studio ' \
'migration_Calendar'
except Exception as err:
print(err)
raise err
else:
return results
def query_user_data_migration_statu(self, user_migration_id: str) -> dict:
try:
results = self.service.transfers().get(dataTransferId=user_migration_id).execute()
except Exception as err:
raise err
else:
return results
applicationDataTransfers 中的 applicationId 的值可以通过 UserDataManage().get_applications_info 方法获取所有的应用ID,部分回显示如下:
注:用户同事只能迁移一个应用数据,需要等到上个应用数据迁移完成后才能执行后续操作否则回报错,所以引入后续数据迁移状态查询函数。
查询用户数据迁移状态
def check_migration_statu(operation_statu: str, statu_info: str, user_info: str) -> dict:
i = 2
# 判断迁移状态,数据迁移完成后跳出循环,最多等待58秒。
try:
for times in range(5):
time.sleep(i)
operation_result = UserDataManage().query_user_data_migration_statu(statu_info)
operation_StatusCode = operation_result['overallTransferStatusCode']
if operation_StatusCode == 'completed':
print('用户邮箱是:{} {}数据迁移完成'.format(user_info, operation_statu))
return {'statu': 'completed', 'info': 'no err'}
else:
print('用户邮箱是:{} 操作是:{}, 当前状态是:{}'.format(user_info, operation_statu, operation_StatusCode))
i += 5
return {'statu': 'err', 'info': '58秒内未完成数据迁移'}
except Exception as err:
print(err)
return {'statu': 'err', 'info': err}
关联函数操作
def main(user_email: str, receive_user_id: str) -> dict:
operations = ['migration_Currents', 'migration_Google_Data_Studio', 'migration_Calendar',
'migration_Drive_and_Docs']
# 获取发送数据用户ID
try:
user_id = UserManageApiRequest().get_user_data(user_email)[user_email]['id']
except Exception as error:
with open('user_get_id_error.txt', 'a+', encoding='utf-8') as r:
r.write('用户邮箱:{},获取用户ID失败,错误信息:{} \n'.format(user_email, error))
return {'statu': 'error', 'info': '获取用户ID失败,详情见user_get_id_error.txt文件信息'}
# 对数据逐个迁移
for one_operation in operations:
try:
operation_result = UserDataManage().user_data_migration(new_user_id=receive_user_id, old_user_id=user_id,
operation=one_operation)
migration_statu_id = operation_result['id']
check_result = check_migration_statu(one_operation, migration_statu_id, user_email)
if check_result['statu'] != 'completed':
err_info = '用户邮箱:{} 数据迁移状态检测失败,原因是:{}'.format(user_email, check_result['info'])
return {'statu': 'check_migration_statu_err', 'info': err_info}
except Exception as err:
err_info = ('用户邮箱:{} 数据迁移失败,原因是 {}'.format(user_email, err))
return {'statu': 'migration_data_err', 'info': err_info}
return {'statu': 'ok', 'info': 'no err'}
启动脚本
if __name__ == "__main__":
err_infos = list()
new_time = time.time()
# 发送数据邮箱,用户邮箱从文本中获取,每行一个邮箱账户。
all_user = open('userinfo.txt').read().split('\n')
# 用户从列表中获取
# all_user = ['456@gmail.com']
# 接受数据邮箱
receive_email = '123@gmail.com'
try:
# 获取用户ID,数据传输时使用的是用户ID
get_receive_email_id = UserManageApiRequest().get_user_data(receive_email)[receive_email]['id']
# 开始迁移用户数据。
for one_email in all_user:
new_time = time.time()
result = main(one_email, get_receive_email_id)
if result['statu'] == 'ok':
# 数据迁移完成后删除用户。
try:
UserManageApiRequest().delete_user(user_email=one_email)
print('用户邮箱:{} 数据迁移完成并已删除耗时:{} \n'.format(one_email, time.time() - new_time))
except Exception as delete_error:
err_infos.append({'email': one_email, 'info': '用户删除失败,错误信息是{}'.format(delete_error)})
print('用户邮箱:{},用户删除失败,错误信息是{} \n'.format(one_email, delete_error))
else:
err_infos.append({'email': one_email, 'info': result['info']})
except Exception as e:
print('获取接受用户ID失败,错误原因是{}'.format(e))
if err_infos:
# 将错误日志写入文本文件
print(err_infos)
with open('user_migration_error_log.txt', 'a+', encoding='utf-8') as user_log:
for one_error_log in err_infos:
user_log.write(str(one_error_log) + '\n')
部分运行结果截图
参考文档
https://developers.google.com/workspace
https://googleapis.github.io/google-api-python-client/docs/dyn/admin_directory_v1.users.html
友情链接
推荐三位老师 网络工程师 python入门指南
王印老师:https://zhuanlan.zhihu.com/p/486260131
九净老师:https://www.zhihu.com/column/feifeiflight
朱嘉盛老师:https://zhuanlan.zhihu.com/p/370526806