PleasanterのWebAPIを内部から内部へ実行する！？

# Pleasanterのサーバスクリプト「httpClient」を使ったUsersの拡張項目の取得

突然ですが、皆様はPleasanterのAPIやスクリプト、サーバースクリプトを利用されたことがありますでしょうか。  
私たちエンジニアはこちらの機能を使い慣れていますが、ユーザ目線で考えると少し難しいと思われます。今回、アサインされている案件で「全ユーザを対象にユーザテーブルの拡張項目で表示非表示制御を実装したい」というご要望から意外な使い方をしたため、本記事でご紹介いたします。  

## はじめに

APIやスクリプト、サーバスクリプトについてよくわからないという方もいらっしゃると思いますので、まずは基礎知識からご紹介いたします。  

## Pleasanterの開発者向け機能について・・・

Pleasanterの開発者向け機能の中で本記事で対象としている下記についてご紹介いたします。  

* API  
* スクリプト  
* サーバスクリプト  

そもそも、上記の3つは下記のように大きく2つに分けられます。  

* 外部用  
  * API  

* 内部用  
  * スクリプト  
  * サーバスクリプト  

### 外部用

#### APIとは・・・？

APIとは外部から対象システムの内部プログラムを実行するためのインタフェースです。インタフェースとは「接点」などの意味を表しますが、この場合ユーザと対象システムとの接点を表す言葉です。  
そして、忘れてはいけないのがセキュリティです。APIは異なるオリジンから実行されるため、認証が必要です。  

そのために利用されるのが**APIキー**です。  

### 内部用

#### スクリプトとは・・・？

クライアント側でAPIを利用するためのプログラムです。  
Pleasanterでは、ほかのプログラム名称と重複が起きないように「$p」という箱の中にAPIを利用するためのいろいろな関数を定義しています。  
APIとの違いは内部で利用されるという点にあります。  
感の良い方はお気づきかと思いますが、内部で利用される(ログインしている状態)であるため、**APIキー**が必要ありません。  

#### サーバスクリプトとは・・・？

サーバ側でAPIを利用するためのプログラムです。  
こちらもスクリプトと同様にAPIキーは必要ありません。  

スクリプトとサーバスクリプトは「レスポンスの情報をどのように扱いたいか」によって使い分けます。  
たとえば、プログラムの実行した際に返却されたレスポンスは両者で下記のように取り扱いが異なります。  

* スクリプト  
    → ユーザがレスポンス内容を見ることができる  
* サーバスクリプト  
    → ユーザがレスポンス内容を見ることができない  

たとえば、レスポンスの内容に登録されている全ユーザの情報が格納されている場合、セキュリティの観点からサーバスクリプトで実装したほうが良いですね。  
この取り扱いの違いは下記のとおりです。  

* スクリプト  
    → クライアント側で実行  
* サーバスクリプト  
    → サーバ側で実行  

クライアント側で実行する場合、リクエストやレスポンスなどの情報をもとにクライアント側で処理し、サーバと通信します。  
反して、サーバ側で実行する場合、リクエストやレスポンスなどの情報も含めサーバ側で処理します。  
そのため、上記のような違いがあるのです。  

## サーバスクリプト「httpClient」

お待たせいたしました。ここからが本記事の本題となります。  

### 要件をクリアするためには・・・？

#### 候補1：スクリプト「$p.apiUsersGet」での実装

要件をクリアするためにはユーザテーブルから該当ユーザの情報を取得するという関数を利用します。  
スクリプトでは、「$p.apiUsersGet」が候補に挙がります。しかし、対象の環境ではユーザによって[「APIの許可」](https://pleasanter.org/manual/user-new)を制御しているため、スクリプトでは実装できません。(APIが許可されていないとスクリプトを実行することができないからですね・・・)   

##### スクリプト例

``` JavaScript
$p.apiUsersGet({
    id: $p.userId(),
    done: function (data) {
        console.log(data.Response.Data[0].Name); // テナント管理者
    }
});
```

#### 候補2：サーバスクリプト「users.Get」での実装

スクリプトでは実装できないということが判明したため、サーバスクリプトで実装することを検討しました。  
サーバスクリプトでは、「users.Get」が候補に挙がります。しかし、こちらではユーザテーブルから該当ユーザの情報を取得できますが、拡張項目は取得できない仕様ということが判明。  

##### スクリプト例

``` JavaScript
let user = users.Get(context.UserId);
context.Log(user.Name); // テナント管理者
```

#### 候補3：サーバスクリプト「httpClient.Post」での実装

サーバスクリプト「users.Get」でも実装できないことが判明しました。そのため、サーバスクリプトからAPIを呼び出してユーザ情報を取得することを検討しました。  
サーバスクリプトでAPIを呼び出すには「httpClient」を利用します。また、PleasanterAPIの呼び出しには「POST」を利用するため「httpClient.Post」を利用します。  
実装した結果、無事にユーザテーブルから該当ユーザの拡張項目を取得することができました！  
ただ、こちらのやり方は少々難しく、下記のような構造になっています。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659914/ff25e75a-904a-11a9-74fd-4edd0adcfa90.png)  

下記のような手順でユーザ情報を取得しています。  

1. httpClient.Post()を実行する。  
2. 外部APIを呼び出すため、一度Pleasanterの外へ移動する。  
3. PleasanterAPI(users/get)を呼び出すため、Pleasanterにアクセスする。  
4. アクセスする際にAPIキーを利用し、認証する。  
5. 外部API経由でユーザ情報を取得する。  

少しまどろっこしくユーザ情報を所得しておりますが、無事に要件を達成できました。  
ただし、このような使い方はパフォーマンス低下を招く恐れがあります。なぜなら、取得する件数に応じて上記の手順を繰り返すからです。つまり、10件取得するには上記を10回、100件取得するには上記を100回繰り返しますので注意してください。  
さらに、外部のサイト(異なるオリジン)でのアクセスには「CORSエラー」というエラーが発生する可能性がありますので、注意が必要です。CORSエラーについては[こちらの記事](https://qiita.com/teppei12345/items/3c71e94da8a98ffc0f87)をご参照ください。  

##### スクリプト例

```JavaScript
//debug//
let data = {
    "ApiVersion": 1.1,
    "ApiKey": "4da・・・・",
    "View": {
        "ColumnFilterHash": {
            "UserId": "[{UserId}]"
        }
    }
}
httpClient.RequestUri = 'http://{ServerName}/api/users/get';
httpClient.Content = JSON.stringify(data);
let response = httpClient.Post();
    context.Log(JSON.parse(response).Response.Data[0].Name); // テナント管理者
```

## おわりに

弊社のサービスには、SIやサポート等がありますが、お客様の環境やご用件などに応じてどのような実装が最適かを判断しなくてはいけません。そのためには、Pleasanterの仕様はもちろん、そのほかの知識も必要になります。  
私は株式会社インプリムに入社して早1年がたちましたが、まだまだ知らないことがたくさんあります。  
いまだに勉強の毎日ですが、その努力が役に立つ時、とても楽しいのでこれからも精進いたします。これからもよろしくお願いいたします。  

# 参考資料

* 開発者向け機能：API  

https://pleasanter.org/manual/api  

* 開発者向け機能：スクリプト  

https://pleasanter.org/manual/script  

* 開発者向け機能：サーバスクリプト  

https://pleasanter.org/manual/server-script  

* 開発者向け機能：スクリプト：$p.apiUsersGet  

https://pleasanter.org/manual/script-api-users-get  

* 開発者向け機能：サーバスクリプト：users  

https://pleasanter.org/manual/server-script-users  

* 開発者向け機能：サーバスクリプト：httpClient  

https://pleasanter.org/manual/server-script-http-client  

* 開発者向け機能：サーバスクリプト：httpClient.Post  

https://pleasanter.org/manual/server-script-http-client-post  

* 開発者向け機能：API：ユーザ操作：ユーザ取得（選択）  

https://pleasanter.org/manual/api-user-get