たとえば、営業チーム向けのソリューションを作成しようとしているとします。営業チームは複数の地域に分割され、各地域にそれぞれの地域マネージャーがいます。BigQuery の販売データセットには、地域別および日付別の売上金額があります。
こうした場合は、地域マネージャーが単一のダッシュボードで自分の地域の販売データのみを表示できるというソリューションを作成するとよいでしょう。
要件
- ダッシュボード閲覧ユーザーは Google アカウントでログインすること。
- ユーザーのメールアドレスと、ユーザーがアクセスできるデータまたは行の間のマッピングが利用可能なこと。
- サービス アカウントが、BigQuery データへのアクセスに使用されること。したがって、請求はダッシュボード提供ユーザーによって一元管理されます。
制限事項
- ダッシュボードでは、最初の表示の際に各閲覧ユーザーから 1 回限りの認証が必要です。
- 閲覧ユーザーはダッシュボードを編集したり、他のユーザーと共有したりすることはできません。
- Workspace をご利用で、管理者が共有を無効にしている場合 ドライブのファイルを [リンクを知っている全員] に設定すると、 Gmail.com アカウントでソリューションを開発できます。
解決策
ソリューションを実装するには、以下のすべてのステップを完了します。
新しいコミュニティ コネクタを作成する
コミュニティ コネクタの仕組み(英語)を視聴し、コミュニティ コネクタのコードラボを完了します。コネクタ作成用のデベロッパー ツールを使うと、開発作業がより効率的かつ簡単になります。
コネクタコードを記述する
getAuthType()
はNONE
を返す必要があります。getConfig()
は空の設定を返す必要があります。- (省略可)ダッシュボードの設定に特定の入力が必要な場合は、ここでユーザー入力をリクエストできます。
getSchema()
はクエリのスキーマを返す必要があります。- (省略可)スキーマの一部として、SQL クエリまたは計算フィールドを使用して、カスタム フィールドと計算を追加できます。
getData()
の実装は後のステップで行います。
マニフェストを更新する
マニフェスト リファレンスを参照し、次を含むすべての必要な情報でマニフェストを完成させます。
dataStudio.forceViewersCredentials
をtrue
に設定します。dataStudio.advancedServices.data
をtrue
に設定します。oauthScopes
には、https://www.googleapis.com/auth/userinfo.email
とhttps://www.googleapis.com/auth/script.external_request
を追加します。詳しくは、Apps Script 向け承認スコープをご覧ください。- (条件付き必須)コネクタで使用されるサービスに関連するすべてのスコープを追加します。
マニフェストは次のようになります。
{
...
"dataStudio": {
"forceViewersCredentials": true,
"advancedServices": {
"data": true
},
...
}
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/userinfo.email"
],
...
}
サービス アカウントを実装する
- Google Cloud プロジェクトでサービス アカウントを作成します。これが課金プロジェクトになります。
- このサービス アカウントには、Cloud プロジェクトでの BigQuery へのアクセス権限が必要です。
- 必要な Identity and Access Management(IAM)の役割:
BigQuery Data Viewer
、BigQuery Job User
- 必要な Identity and Access Management(IAM)の役割:
- JSON ファイルをダウンロードして、サービス アカウント キーを取得します。コネクタ プロジェクトのスクリプト プロパティにキーを保存します。
- Apps Script プロジェクトに Apps Script 向け OAuth2 ライブラリを含めます。
- サービス アカウントに必要な OAuth2 コードを実装します。
var SERVICE_ACCOUNT_CREDS = 'SERVICE_ACCOUNT_CREDS';
var SERVICE_ACCOUNT_KEY = 'private_key';
var SERVICE_ACCOUNT_EMAIL = 'client_email';
var BILLING_PROJECT_ID = 'project_id';
/**
* Copy the entire credentials JSON file from creating a service account in GCP.
*/
function getServiceAccountCreds() {
return JSON.parse(scriptProperties.getProperty(SERVICE_ACCOUNT_CREDS));
}
function getOauthService() {
var serviceAccountCreds = getServiceAccountCreds();
var serviceAccountKey = serviceAccountCreds[SERVICE_ACCOUNT_KEY];
var serviceAccountEmail = serviceAccountCreds[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']);
}
getData()
を実装する
- BigQuery クエリを作成します。
- メールを使用して、メールとデータ間のマッピングを検索します。
- JOIN または WHERE 句を使用して、データをフィルタ処理します。
- 有効なユーザーのメールアドレスを取得します(ユーザー ID についての記事を参照)。
- Looker Studio の Advanced Services を使用してクエリ構成を返します。
取得します。
- 作成されたクエリ、課金プロジェクト、サービス アカウント OAuth トークンを渡します。
- (条件付き必須)コネクタ
getConfig
を介してユーザー入力を取得している場合、入力を BigQuery パラメータとして組み込む必要があります。
ダッシュボードを作成する
- コネクタのデプロイとバージョンの仕組みを理解します。
- コネクタの本番環境デプロイを作成します。
- 本番環境デプロイを使用して、データソースと新しいレポートを Looker Studio です
- レポートにすべてのテーブルとグラフを追加します。
- ダッシュボードをユーザーと共有する次のステップに進みます。
ユーザーがダッシュボードを利用できるようにする
- 選択したユーザーまたは「リンクを知っている全員」にコネクタ スクリプトを共有します。
- 選択したユーザーまたは「リンクを知っている全員」にダッシュボードを共有します。
- (省略可)URL Shortener サービスを使用して、ダッシュボード URL のショートリンクを作成します。短縮 URL をユーザーに共有します。これにより、ダッシュボードの URL を必要に応じて後で置き換えることができます。
- (省略可)レポートに Google アナリティクスを設定して、ダッシュボードの使用状況を測定します。
サンプルコード
以下は、コネクタの完全なサンプルコードです。
main.js
var cc = DataStudioApp.createCommunityConnector();
var scriptProperties = PropertiesService.getScriptProperties();
function isAdminUser() {
return true;
}
function getAuthType() {
var AuthTypes = cc.AuthType;
return cc
.newAuthTypeResponse()
.setAuthType(AuthTypes.NONE)
.build();
}
function getConfig(request) {
var config = cc.getConfig();
config
.newInfo()
.setId('generalInfo')
.setText('This is an example connector to showcase row level security.');
return config.build();
}
function getFields() {
var fields = cc.getFields();
var types = cc.FieldType;
var aggregations = cc.AggregationType;
fields
.newDimension()
.setId('region')
.setName('Region')
.setType(types.TEXT);
fields
.newMetric()
.setId('sales')
.setName('Sales')
.setType(types.NUMBER)
.setAggregation(aggregations.SUM);
fields
.newDimension()
.setId('date')
.setName('Date')
.setType(types.YEAR_MONTH_DAY);
return fields;
}
function getSchema(request) {
return {schema: getFields().build()};
}
var SERVICE_ACCOUNT_CREDS = 'SERVICE_ACCOUNT_CREDS';
var SERVICE_ACCOUNT_KEY = 'private_key';
var SERVICE_ACCOUNT_EMAIL = 'client_email';
var BILLING_PROJECT_ID = 'project_id';
/**
* Copy the entire credentials JSON file from creating a service account in GCP.
*/
function getServiceAccountCreds() {
return JSON.parse(scriptProperties.getProperty(SERVICE_ACCOUNT_CREDS));
}
function getOauthService() {
var serviceAccountCreds = getServiceAccountCreds();
var serviceAccountKey = serviceAccountCreds[SERVICE_ACCOUNT_KEY];
var serviceAccountEmail = serviceAccountCreds[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']);
}
var BASE_SQL =
'SELECT d.region, d.sales, d.date ' +
'FROM `datastudio-solutions.row_level_security.data` d ' +
'INNER JOIN `datastudio-solutions.row_level_security.access` a ' +
'ON d.region = a.region ' +
'where a.email=@email';
function getData(request) {
var accessToken = getOauthService().getAccessToken();
var serviceAccountCreds = getServiceAccountCreds();
var billingProjectId = serviceAccountCreds[BILLING_PROJECT_ID];
var email = Session.getEffectiveUser().getEmail();
var bqTypes = DataStudioApp.createCommunityConnector().BigQueryParameterType;
return cc
.newBigQueryConfig()
.setAccessToken(accessToken)
.setBillingProjectId(billingProjectId)
.setUseStandardSql(true)
.setQuery(BASE_SQL)
.addQueryParameter('email', bqTypes.STRING, email)
.build();
}