ApiKey なしでも ApiVersion を反映する改修
本体の標準機能ではありません
このページは本体を改修する場合の設計メモです。現行の動作と設定での回避策は ApiVersion の決まり方 にまとめています。多くの場合は、改修せずに Api.json の Compatibility_1_3_12 を false にすれば足ります。
前提にした現行の実装(1.5.8.1)
ソースへのリンクは Implem/Implem.Pleasanter の 1.5.8.1(コミット fdcbb3f8)固定です。
Context.SetApiOptions() は、Compatibility_1_3_12 が true のとき、リクエストに ApiKey があるときだけリクエストの ApiVersion を Context.ApiVersion に入れます(Context.cs#L521-L536)。Compatibility_1_3_12 は 1.3.12 当時の「ApiKey を指定しないリクエストで ApiVersion が正しくセットされない」不具合を修正したときに、不具合のある状態で作られた既存のスクリプトの動きを変えないために入った互換フラグです(本体の変更履歴による。1.5.8.1 のソースにその説明のコメントは残っていません)。
変更案
Compatibility_1_3_12 の分岐で ApiKey の条件を外します。
private void SetApiOptions(Api api)
{
ApiVersion = api?.ApiVersion ?? ApiVersion;
ApiSsCache = api?.SsCache ?? false;
}Compatibility_1_3_12 を残したまま if (api != null) にする書き方もありますが、結果は同じです。ApiSsCache の扱いは今と変わりません。
影響の確認
ApiVersion が使われる場所
Context.ApiVersionの初期値はApi.jsonのVersionで(Context.cs#L130)、値を変えるのはSetApiOptions()だけです。Context.ApiVersionは、各モデルのGetByApi()が返す API モデルのApiVersionに写されます。ApiVersionで処理が分かれるのは_BaseApiModelのシリアライズ(OnSerializing)とデシリアライズ(OnDeserialized)の 2 か所だけで、1.1 未満なら個別プロパティ(ClassAなど)、1.1 以上なら辞書(ClassHashなど)になります(_BaseApiModel.cs#L815-L818、_BaseApiModel.cs#L1585-L1588)。認証・権限・データの読み書き・入力検証には使われていません。Compatibility_1_3_12を参照しているのはSetApiOptions()だけです。
リクエスト(Create・Update など)の本文を API モデルとして読むときの ApiVersion は、JSON に書かれた値(省略時は初期値)で、Context.ApiVersion とは別です。つまりこの変更で変わるのは、レスポンスの形だけです。
図を読み込み中…
リクエストの型ごとの結果
リクエストボディは RequestDataString から Api として読まれます。API のリクエストなら JSON 本文、画面のフォーム送信ならフォームの文字列です(Context.cs#L134)。JSON として読めないと Deserialize は例外を握りつぶして null を返します(Jsons.cs#L22-L32)。また Api.ApiVersion の初期値も Api.json の Version です(Api.cs#L11)。
| リクエスト | 現行 | 変更後 |
|---|---|---|
| 画面のフォーム送信 | api が null なので Version のまま | 同じ |
| ApiKey あり・ApiVersion 指定あり | 指定値 | 同じ |
| ApiKey あり・ApiVersion 省略 | Version(Api の初期値) | 同じ |
ApiKey なし・ApiVersion 省略($p.apiGet の通常の使い方) | Version | Version(Api の初期値なので同じ) |
| ApiKey なし・ApiVersion 指定あり | 無視されて Version | 指定値 |
変わるのは最後の行、つまり「ApiKey なしで ApiVersion を明示したリクエスト」だけです。
リスク
| 観点 | 評価 |
|---|---|
| 省略時の既定値 | Api と Context の初期値が同じ Version なので変わらない |
| フォーム送信 | api が null になるので変わらない |
| 悪意のある指定 | ApiVersion で変わるのはレスポンスの形だけで、返るデータの範囲や権限は変わらない |
| 既存のスクリプト | ApiVersion を省略しているスクリプトは変わらない。明示して「効いていない」前提で書かれたスクリプト(例えば ApiVersion: 1.1 と書きつつ 1.0 形式のレスポンスを読んでいる)だけが影響を受ける |
最後の点が、互換フラグが守っていたケースです。改修する場合は、画面のスクリプト($p.api* の呼び出し)から ApiVersion の指定を検索して、レスポンスの読み方と合っているかを確かめてください。