Google Sheets AddOn - AppScript 和 BigQuery 通过服务帐户集成
Google Sheets AddOn - AppScript & BigQuery Integration via Service Account
我有一个 Google 表格工作区插件,最近做了一些集成 BigQuery 的工作。本质上,BigQuery 保存着每本书的记录,每本书都有作者、书名等,而我的插件允许人们将他们读过的书拉到他们的 sheet 中。 sheet 中的第一列允许人们从数据库中的所有作者中进行选择,根据该选择,第二列填充来自 BigQuery 的数据以及该作者的所有书籍等。不需要我的AddOn 访问用户的 BigQuery,他们只访问 'my' BgQuery。
一切正常,但是当我提交我的插件以供批准时,我被告知
Unfortunately, we cannot approve your request for the use of the following scopes
https://www.googleapis.com/auth/bigquery
We recommend using service accounts for this type of information exchange.
这似乎很公平,阅读服务帐户似乎更适合我的用例。我已经完成了创建服务帐户的过程并下载了我的安全详细信息 json 文件,但是我只是不知道如何从 AppScript 实际查询 BigQuery。
在我的非服务帐户方法中,我在 AppScript 中安装了 BigQuery 库,基本上 运行
var queryResults = BigQuery.Jobs.query(request, projectId);
我一直在尝试从 https://developers.google.com/datastudio/solution/blocks/using-service-accounts
的示例开始工作
function getOauthService() {
var serviceAccountKey = getServiceAccountCreds('SERVICE_ACCOUNT_KEY');// from private_key not private_key_id of JSON file
var serviceAccountEmail = getServiceAccountCreds('SERVICE_ACCOUNT_EMAIL');
return OAuth2.createService('RowLevelSecurity')
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey(serviceAccountKey)
.setIssuer(serviceAccountEmail)
.setPropertyStore(scriptProperties)
.setCache(CacheService.getScriptCache())
.setScope(['https://www.googleapis.com/auth/bigquery.readonly']);
}
function getData(request) {
var accessToken = getOauthService().getAccessToken();
var billingProjectId = getServiceAccountCreds('BILLING_PROJECT_ID');
// var email = Session.getEffectiveUser().getEmail();
// return cc
// .newBigQueryConfig()
// .setAccessToken(accessToken)
// .setBillingProjectId(billingProjectId)
// .setUseStandardSql(true)
// .setQuery(BASE_SQL)
// .addQueryParameter('email', bqTypes.STRING, email)
// .build();
}
我已经注释掉了上面与
相关的代码
var cc = DataStudioApp.createCommunityConnector();
在上面的教程中,因为我没有使用 DataStudio,但我真的不确定用什么替换它,所以我可以通过服务帐户使用 AppScript 查询 BigQuery。任何人都可以提供任何建议吗?
根据上面评论中@TheAddonDepot 的建议,我修改后的代码现在如下所示:
function getBigQueryService() {
return (
OAuth2.createService('BigQuery')
// Set the endpoint URL.
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the private key and issuer.
.setPrivateKey(JSON_CREDS.private_key) // from the json file downloaded when you create service account
.setIssuer(JSON_CREDS.client_email). // from the json file downloaded when you create service account
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getScriptProperties())
// Caching
.setCache(CacheService.getUserCache())
// Locking
.setLock(LockService.getUserLock())
// Set the scopes.
.setScope(['https://www.googleapis.com/auth/bigquery.readonly'])
// .setScope('https://www.googleapis.com/auth/bigquery')
)
}
function queryData(){
const bigQueryService = getBigQueryService()
if (!bigQueryService.hasAccess()) {
Logger.log("BQ ERROR IS "+ bigQueryService.getLastError())
}
//const projectId = bigqueryCredentials.project_id
var projectId = "<yourprojectid>"
let url = 'https://bigquery.googleapis.com/bigquery/v2/projects/<yourprojectid>/queries'; //projectID is taken from the security json file for the service account, although it doesn't seem to matter if you use the project code
const headers = {
Authorization: `Bearer ${bigQueryService.getAccessToken()}`,
'Content-Type': 'application/json',
}
var data = {query:"<your query>",useLegacySql:false};
const options = {
method: 'post',
headers,
//contentType: 'application/json',
payload: JSON.stringify(data),
muteHttpExceptions: true // on for debugging
}
try {
const response = UrlFetchApp.fetch(url, options)
const result = JSON.parse(response.getContentText())
Logger.log("here is result "+ JSON.stringify(result))
} catch (err) {
console.error(err)
}
}
我有一个 Google 表格工作区插件,最近做了一些集成 BigQuery 的工作。本质上,BigQuery 保存着每本书的记录,每本书都有作者、书名等,而我的插件允许人们将他们读过的书拉到他们的 sheet 中。 sheet 中的第一列允许人们从数据库中的所有作者中进行选择,根据该选择,第二列填充来自 BigQuery 的数据以及该作者的所有书籍等。不需要我的AddOn 访问用户的 BigQuery,他们只访问 'my' BgQuery。
一切正常,但是当我提交我的插件以供批准时,我被告知
Unfortunately, we cannot approve your request for the use of the following scopes
https://www.googleapis.com/auth/bigquery
We recommend using service accounts for this type of information exchange.
这似乎很公平,阅读服务帐户似乎更适合我的用例。我已经完成了创建服务帐户的过程并下载了我的安全详细信息 json 文件,但是我只是不知道如何从 AppScript 实际查询 BigQuery。
在我的非服务帐户方法中,我在 AppScript 中安装了 BigQuery 库,基本上 运行
var queryResults = BigQuery.Jobs.query(request, projectId);
我一直在尝试从 https://developers.google.com/datastudio/solution/blocks/using-service-accounts
的示例开始工作function getOauthService() {
var serviceAccountKey = getServiceAccountCreds('SERVICE_ACCOUNT_KEY');// from private_key not private_key_id of JSON file
var serviceAccountEmail = getServiceAccountCreds('SERVICE_ACCOUNT_EMAIL');
return OAuth2.createService('RowLevelSecurity')
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey(serviceAccountKey)
.setIssuer(serviceAccountEmail)
.setPropertyStore(scriptProperties)
.setCache(CacheService.getScriptCache())
.setScope(['https://www.googleapis.com/auth/bigquery.readonly']);
}
function getData(request) {
var accessToken = getOauthService().getAccessToken();
var billingProjectId = getServiceAccountCreds('BILLING_PROJECT_ID');
// var email = Session.getEffectiveUser().getEmail();
// return cc
// .newBigQueryConfig()
// .setAccessToken(accessToken)
// .setBillingProjectId(billingProjectId)
// .setUseStandardSql(true)
// .setQuery(BASE_SQL)
// .addQueryParameter('email', bqTypes.STRING, email)
// .build();
}
我已经注释掉了上面与
相关的代码var cc = DataStudioApp.createCommunityConnector();
在上面的教程中,因为我没有使用 DataStudio,但我真的不确定用什么替换它,所以我可以通过服务帐户使用 AppScript 查询 BigQuery。任何人都可以提供任何建议吗?
根据上面评论中@TheAddonDepot 的建议,我修改后的代码现在如下所示:
function getBigQueryService() {
return (
OAuth2.createService('BigQuery')
// Set the endpoint URL.
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the private key and issuer.
.setPrivateKey(JSON_CREDS.private_key) // from the json file downloaded when you create service account
.setIssuer(JSON_CREDS.client_email). // from the json file downloaded when you create service account
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getScriptProperties())
// Caching
.setCache(CacheService.getUserCache())
// Locking
.setLock(LockService.getUserLock())
// Set the scopes.
.setScope(['https://www.googleapis.com/auth/bigquery.readonly'])
// .setScope('https://www.googleapis.com/auth/bigquery')
)
}
function queryData(){
const bigQueryService = getBigQueryService()
if (!bigQueryService.hasAccess()) {
Logger.log("BQ ERROR IS "+ bigQueryService.getLastError())
}
//const projectId = bigqueryCredentials.project_id
var projectId = "<yourprojectid>"
let url = 'https://bigquery.googleapis.com/bigquery/v2/projects/<yourprojectid>/queries'; //projectID is taken from the security json file for the service account, although it doesn't seem to matter if you use the project code
const headers = {
Authorization: `Bearer ${bigQueryService.getAccessToken()}`,
'Content-Type': 'application/json',
}
var data = {query:"<your query>",useLegacySql:false};
const options = {
method: 'post',
headers,
//contentType: 'application/json',
payload: JSON.stringify(data),
muteHttpExceptions: true // on for debugging
}
try {
const response = UrlFetchApp.fetch(url, options)
const result = JSON.parse(response.getContentText())
Logger.log("here is result "+ JSON.stringify(result))
} catch (err) {
console.error(err)
}
}