// GraalJS Script (engine type: 2)
/*
NOTES
- Google Group for Google Workspace can be used as a team mailing list.
- This addon automatically retrieves the list of emails via Google API. (Admin SDK Directory API)
- The list of all members includes all roles (OWNER, MANAGER, and MEMBER).
- Up to 2000 members can be obtained through this addon (automated step).
- The Google Group itself can have an unlimited number of members.
- https://support.google.com/a/answer/6099642?hl=en#zippy=%2Cmembership
- https://support.google.com/a/answer/167085?hl=en What is the maximum number ...
NOTES-ja
- ビジネス向けGoogleグループは、メーリングリストとして利用ができます。(Google Workspace)
- このアドオンは、登録メール一覧を Google API 経由で自動取得します。(Admin SDK Directory API)
- 取得した一覧には、全てのロール(オーナー・マネージャー・メンバー)が含まれます。
- このアドオン(自動処理)を通じて取得できる一覧は、最大2000件までです。
- Google Group 自体には、メンバー数の上限はありません。
- https://support.google.com/a/answer/6099642?hl=ja 参加できるグループ数
- https://support.google.com/a/answer/167085?hl=ja グループのメンバー数に上限は…
*/
/*
APPENDIX
- Up to 200 items can be retrieved by API request.
- If the response JSON contains a "nextPageToken" propety, get the next 200 items.
- Questetra BPMS limits the number of requests to 10.
- https://questetra.zendesk.com/hc/en-us/articles/360002260611-M230
- OAuth Setting sample [HTTP Authorization Setting]
- "Authorization Endpoint URL"
- https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
- "Token Endpoint URL"
- https://accounts.google.com/o/oauth2/token
- to get your "ClientId" and "Secret"
- Access to https://console.developers.google.com/apis/credentials
- Authorization Scopes (one of the following)
- https://apps-apis.google.com/a/feeds/groups/
- https://www.googleapis.com/auth/admin.directory.group
- https://www.googleapis.com/auth/admin.directory.group.member
- https://www.googleapis.com/auth/admin.directory.group.member.readonly
- https://www.googleapis.com/auth/admin.directory.group.readonly
APPENDIX-ja
- 登録アドレスが多い場合、一度のAPI通信で200件ずつ取得します。
- レスポンスJSONに "nextPageToken" プロパティが含まれる場合、次の200件を取得します。
- Questetra BPMS の制約により、リクエストは10回に制限されます。
- https://questetra.zendesk.com/hc/ja/articles/360002260611-M230
- OAuth 設定例([HTTP認証設定]の例)
- "Authorization Endpoint URL"
- https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
- "Token Endpoint URL"
- https://accounts.google.com/o/oauth2/token
- なお "ClientId" と "Secret" は開発者コンソールにアクセスして取得します。
- Access to https://console.developers.google.com/apis/credentials
- 認可スコープ(以下のいずれか)
- https://apps-apis.google.com/a/feeds/groups/
- https://www.googleapis.com/auth/admin.directory.group
- https://www.googleapis.com/auth/admin.directory.group.member
- https://www.googleapis.com/auth/admin.directory.group.member.readonly
- https://www.googleapis.com/auth/admin.directory.group.readonly
*/
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzSetting = configs.get( "AuthzConfA" ); // required (Authz by Basic_AuthN)
engine.log( " AutomatedTask Config: Authz Setting: " + strAuthzSetting );
const strGroupEmail = configs.get( "StrConfB1" ) + ""; // "groupKey"
engine.log( " AutomatedTask Config: Group Email: " + strGroupEmail );
if( strGroupEmail === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {B1 Group Address} not specified \n" );
}
const strPocketList = configs.getObject( "SelectConfC1" );
const numPocketList = configs.getObject( "SelectConfC2" );
const strPocketOwners = configs.getObject( "SelectConfD1" );
const strPocketManagers = configs.getObject( "SelectConfE1" );
const strPocketGroups = configs.getObject( "SelectConfF1" );
//// == Data Retrieving / ワークフローデータの参照 ==
// (nothing)
//// == Calculating / 演算 ==
let numList = 0;
let strList = "";
let strOwners = "";
let strManagers = "";
let strGroups = "";
/// Retrieves a paginated list of all members in a group.
/// (Google Workspace Developer > Admin SDK > Directory API)
/// https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/list
let strPageToken = "firstpage"; // Token to specify next page in the list.
let numLoop = 0;
const NumLoopLimit = 10;
while( strPageToken !== "" ){
// request1, prepare
let getUri1 = "https://admin.googleapis.com/admin/directory/v1/groups/" +
strGroupEmail + "/members";
let request1 = httpClient.begin(); // HttpRequestWrapper
request1 = request1.authSetting( strAuthzSetting ); // with "Authorization: Bearer XX"
if( strPageToken !== "firstpage" ){
request1 = request1.queryParam( "pageToken", strPageToken );
}
// request1, try
const response1 = request1.get( getUri1 ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + getUri1 );
const response1Code = response1.getStatusCode() + ""; // (primitive string)
const response1Body = response1.getResponseAsString() + "";
engine.log( " AutomatedTask ApiResponse Status: " + response1Code );
if( response1Code !== "200"){
throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
response1Code + "\n" + response1Body + "\n" );
}
// response1, parse
/* engine.log( response1Body ); // debug
response sample
{
"kind": "admin#directory#members",
"etag": "\"SufirXXXXXXcAYyYYYYYNcnrWZZZZZeibFuWWWWW5qw/fXXXXXt2OWzYYYYYI1iYkZZZZZM\"",
"members": [
{
"kind": "admin#directory#member",
"etag": "\"SufirXXXXXXcAYyYYYYYNcnrWZZZZZeibFuWWWWW5qw/xXXXXXgPC-FYYYYYyO6UEZZZZZQ\"",
"id": "117810000059687111119",
"email": "example1@example.com",
"role": "OWNER",
"type": "USER",
"status": "ACTIVE"
},
{ ◆ },
{
"kind": "admin#directory#member",
"etag": "\"SufirXXXXXXcAYyYYYYYNcnrWZZZZZeibFuWWWWW5qw/cXXXXX0LpJ7YYYYYAxBQwZZZZZY\"",
"id": "03rdc00000eo8wd",
"email": "example199@example.com",
"role": "MEMBER",
"type": "GROUP",
"status": "ACTIVE"
},
{
"kind": "admin#directory#member",
"etag": "\"SufirXXXXXXcAYyYYYYYNcnrWZZZZZeibFuWWWWW5qw/yXXXXX1Sn-MYYYYYPOxTjZZZZZo\"",
"id": "112240000028969111113",
"email": "example200@example.com",
"role": "MEMBER",
"type": "USER"
}
],
"nextPageToken": "IiEKHXXXXXuJ8hwYYYYYdWtpaZZZZZFAZ21WWWWWY29tGXXX"
}
*/
const response1Obj = JSON.parse( response1Body );
engine.log( " AutomatedTask ListAdded [" + numLoop + "] : " + response1Obj.members.length );
numList += response1Obj.members.length;
for( let i = 0; i < response1Obj.members.length; i++ ){
strList += response1Obj.members[i].email + "\n";
if( response1Obj.members[i].role === "OWNER" ){
strOwners += response1Obj.members[i].email + "\n";
}
if( response1Obj.members[i].role === "MANAGER" ){
strManagers += response1Obj.members[i].email + "\n";
}
if( response1Obj.members[i].type === "GROUP" ){
strGroups += response1Obj.members[i].email + "\n";
}
}
if( response1Obj.hasOwnProperty('nextPageToken') ){
strPageToken = response1Obj.nextPageToken;
}else{
strPageToken = "";
}
numLoop ++;
if( numLoop === NumLoopLimit ){
strPageToken = "";
}
} // end of "while()"
// Remove LF code at the end of multiple lines
strList = strList.replace(/\n*$/, "");
strOwners = strOwners.replace(/\n*$/, "");
strManagers = strManagers.replace(/\n*$/, "");
strGroups = strGroups.replace(/\n*$/, "");
//// == Data Updating / ワークフローデータへの代入 ==
if( strPocketList !== null ){
engine.setData( strPocketList, strList );
}
if( numPocketList !== null ){
engine.setData( numPocketList, new java.math.BigDecimal( numList ) );
}
if( strPocketOwners !== null ){
engine.setData( strPocketOwners, strOwners );
}
if( strPocketManagers !== null ){
engine.setData( strPocketManagers, strManagers );
}
if( strPocketGroups !== null ){
engine.setData( strPocketGroups, strGroups );
}
} //////// END "main()" /////////////////////////////////////////////////////////////////