ユーザーの参加グループをPHPで出力(Google Workspace)

前回はGAS(Google Apps Script)でスプレッドシートに出力しましたが、以下の問題がありました。

・管理権限者しか実行できない
・出力が遅い

ですので、今回はAPIを利用して誰でも早く出力することにしました。

前提条件および前準備

Google Workspace Admin SDK > Directory APIにも前提条件として記述されてますが、以下の準備が必要です。

・PHP5.4以上、コマンドライン(CLI)とJSONが利用可能な状態
・Composerのインストール
・Google WorkspaceドメインへのAPIアクセスの有効化
・管理者権限を持つGoogleアカウント

Composerについては、以下のコマンドで作業ディレクトリに設置されます。

# curl -s http://getcomposer.org/installer | php

設置されたcomposer.pharを使用して、Googleクライアントライブラリをインストールします。

# php composer.phar require google/apiclient:^2.0

Google Workspace Admin SDK > Directory APIのページにある『quickstart.php』を土台として利用します。

# php quickstart.php

正常に動作すると『Open the following link in your browser:』が表示されますので、表示されたURLをブラウザを利用してアクセスします。
すると認証画面に遷移し、認証を許可するとコードが表示されますのでコピーしてください。
表示されたコードをコマンドラインの『Enter Verification code:』の場所に貼り付けます。

サンプルコードを修正し、Googleグループの登録状況を出力できるようにする

今回は以下の動作を利用可能としてます

・誰がどのグループ(メーリングリスト)に参加しているかを確認できます。
・どのグループ(メーリングリスト)に誰が参加しているかを確認できます。

WebUIはこんな感じです

[16行目~]利用するスコープを記述します
[22行目]利用するAPIのクライアントIDを、サーバー内に設置し、そのパスとファイル名を記述します
[30行目]前準備にて行った認証成功時に指定のファイルが出力されます。利用するスコープを変更するとこのファイルの再作成が必要です
[70行目~]Google Workspace利用ドメイン(先頭に@つける)を記述
[76行目~]WebUIにて70行目に記述したドメイン以外の入力を受け付けない様にする。
[137行目~]個人(プライベート)アドレスなどが入っていた場合、先頭5文字を伏字にする

[php]
<?php
require __DIR__ . '/vendor/autoload.php';

//if (php_sapi_name() != 'cli') {
//	throw new Exception('This application must be run on the command line.');
//}

/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient()
{
	$client = new Google_Client();
	$client->setApplicationName('G Suite Directory API PHP Quickstart');
	$client->setScopes(implode(' ', array(
		'https://www.googleapis.com/auth/admin.directory.group.readonly',
		'https://www.googleapis.com/auth/admin.directory.group.member.readonly',
		'https://www.googleapis.com/auth/admin.directory.user.readonly'
	)));

	$client->setAuthConfig('OAuth2.0 クライアントIDを記述');
	$client->setAccessType('offline');
	$client->setPrompt('select_account consent');

	// Load previously authorized token from a file, if it exists.
	// The file token.json stores the user's access and refresh tokens, and is
	// created automatically when the authorization flow completes for the first
	// time.
	$tokenPath = 'group_token.json';
	if (file_exists($tokenPath)) {
		$accessToken = json_decode(file_get_contents($tokenPath), true);
		$client->setAccessToken($accessToken);
	}

	// If there is no previous token or it's expired.
	if ($client->isAccessTokenExpired()) {
		// Refresh the token if possible, else fetch a new one.
		if ($client->getRefreshToken()) {
			$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
		} else {
			// Request authorization from the user.
			$authUrl = $client->createAuthUrl();
			printf("Open the following link in your browser:\n%s\n", $authUrl);
			print 'Enter verification code: ';
			$authCode = trim(fgets(STDIN));

			// Exchange authorization code for an access token.
			$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
			$client->setAccessToken($accessToken);

			// Check to see if there was an error.
			if (array_key_exists('error', $accessToken)) {
				throw new Exception(join(', ', $accessToken));
			}
		}
		// Save the token to a file.
		if (!file_exists(dirname($tokenPath))) {
			mkdir(dirname($tokenPath), 0700, true);
		}
		file_put_contents($tokenPath, json_encode($client->getAccessToken()));
	}
	return $client;
}




// Get the API client and construct the service object.
$domain = "Google Workspace利用ドメイン(先頭に@つける)";
$eFlag = false; // エラーフラグ
$sFlag = false; // 検索フラグ
$token = ""; // nextPageToken用
$select = $_POST["select"];
$email = $_POST["email"];	
if(strpos($email, $domain) != true){
	$eFlag = true;
}

if(strlen($email) && strlen($select) && !$eFlag){

	switch($select) {

		// アドレスから参加グループ(ML)を検索する
		case "1":

			while(!$endFlag){ // 一度に最大200件しか抽出できないので、[nextPageToken]が出力している間、繰り返す
				$client = getClient();
				$service = new Google_Service_Directory($client);

				$optParams = array(
				  'userKey' => $email,
				  'maxResults' => 200,
				  'pageToken' => $token
				);

				$group = $service->groups->listGroups($optParams);
				for($i = 0; $i < count($group); $i++){
					$ml_arr[$i] = $group[$i]["email"];
				}


				if($group["nextPageToken"] == null){
					$endFlag = true;
				}else{
					$token = $group["nextPageToken"];
				}
			}


			if(count($ml_arr) >= 1){
				$sFlag = true;
			}else{
				$sFlag = false;
			}			

			$msg = "<span id=\"s_address\">".$email."</span>は<span id=\"hit_count\">".count($ml_arr)."</span>個のメーリングリストに参加してます\n";

			break;

		// グループ(ML)アドレスから参加者を検索する
		case "2":

			$private_Flag = false;
			while(!$endFlag){ // 一度に最大200件しか抽出できないので、[nextPageToken]が出力している間、繰り返す
				$client = getClient();
				$service = new Google_Service_Directory($client);

				$optParams = array(
				  'maxResults' => 200,
				  'pageToken' => $token
				);

				$member = $service->members->listMembers($email,$optParams);
				for($i = 0; $i < count($member); $i++){
					// Google Workspace利用ドメイン以外は先頭5文字を伏字を入れる
					if(strpos($member[$i]["email"], $domain) != true){
						$email_arr = explode("@",$member[$i]["email"]);
						$email_arr[0] = str_repeat('*',5) . mb_substr($email_arr[0],5,mb_strlen($email_arr[0], 'UTF8'),'UTF8');
						$ml_arr[$i] = $email_arr[0]."@".$email_arr[1];
						$private_Flag = true;
					}else{	
						$ml_arr[$i] = $member[$i]["email"];
					}
				}


				if($group["nextPageToken"] == null){
					$endFlag = true;
				}else{
					$token = $member["nextPageToken"];
				}
			}


			if(count($ml_arr) >= 1){
				$sFlag = true;
			}else{
				$sFlag = false;
			}			

			$msg = "<span id=\"s_address\">".$email."</span>には<span id=\"hit_count\">".count($ml_arr)."</span>個のメールアドレスが参加してます\n";
			if($private_Flag){
				$msg .= "
".$domain."以外は伏字にしております"; // 伏字に対する注釈
			}

			break;


	}	

	

}else{
	$sFlag = false;
}

?>
[/php]

WebUIはこんな感じ

[php]
<form action="index.php" method="post">
<div id="form_select">
<select name="select">
<option value="1">アドレスから参加グループ(ML)を検索する</option>
<option value="2">グループ(ML)アドレスから参加者を検索する</option>
</select>
</div>

<span id="form_title">検索メールアドレス</span>
<span id="form_data"><input type="text" size="50" name="email" placeholder="メールアドレスを入力してください"></span>

<div id="form_submit"><input type="submit" value="検索"></div>
</form>

<?php
if($sFlag){
	echo "

\n";
	echo $msg;
	echo "

\n";
	foreach($ml_arr as $key => $val){
		echo $val."
\n";
	}
	if(count($ml_arr) > 200){
		echo "

\n";
		echo "最大数(200)を超えましたので、これ以上の表示は管理者に伝えてください\n";
	}

}
?>
[/php]

end