JavaScriptからでもRedmineのREST APIを実行することはできる。
しかしREST APIの実行にはBASIC認証かログインユーザーのapikeyが必要になる。
この記事では少々トリッキーながらJavaScriptからログインユーザーのapikeyを取得し、実際にREST APIを実行してみる。
動作確認は Redmine 2.6系 で行った。
REST APIを使わず、チケット一覧のコンテキストメニューが使用するbulk_update
を利用する記事はこちら。
RedmineのJavaScriptからbulk_updateを使用する
ログインユーザーのapikeyの取得
apikeyを取得するようなAPIは存在しない。
よってログインユーザーの「個人設定」をスクレイピングして取得する。
(下記コードは、当然ながらRedmineのバージョンアップなどで動かなくなる可能性はある)
// Redmine 3.1以前版。
// 3.1以降のいずれかのバージョンからはajaxでapikeyが埋め込まれるためこの方法だと失敗する。
// REST APIがONになっていなければapikeyには空文字が入る。
let apikey = "";
$.get('/my/account').done(function(data){
apikey = $("#api-access-key", $(data)).first().text();
});
// Redmine 3.1以降版。専用ページなので読み込み負荷は若干低いはず。
// REST APIのON/OFFに関わらずapikeyにはAPIキーの文字列が入る。
let apikey = "";
$.get('/my/api_key').done(function(data){
apikey = $('#content > div.box > pre', $(data)).first().text();
});
REST APIの実行
RedmineのAPIリファレンスを参考にしながら、ajax等でREST APIを叩く。
$.ajax({
type: 'get',
url: '/issues/7.json',
data: {include:'relations'},
headers: {'X-Redmine-API-Key': apikey},
dataType: 'text',
contentType: 'application/json',
})
.done((strJson) => console.log(JSON.parse(strJson)))
簡単にapikeyの取得とREST APIを続けて書くなら以下のようになるだろうか。
$.get('/my/account')
.then(
// マイページをスクレイピングしてapikeyを取得
(html) => {
return $("#api-access-key", $(html)).first().text();
}
)
.then(
// REST APIでチケット詳細を取得
(apikey) => {
return $.ajax({
type: 'get',
url: '/issues/15780.json',
data: {include:'relations'},
headers: {'X-Redmine-API-Key': apikey},
dataType: 'text',
contentType: 'application/json',
});
}
)
.then(
// 取得したチケット情報を表示
(json) => console.log(json)
)
雑感
最初はapikeyを入力させるダイアログを作成し、Web Storage経由でapikeyを各画面で使い回す方法も考えた。
しかしRedmineの内部フックを使っているわけではないため、ログアウトしても前のユーザーのapikeyが残ってしまうのはセキュリティ的にかなりよくない。
(REST APIでアクセスできるデータを調べると分かるが、ユーザーのアクセス権限内ならばほぼ全てのデータを大量に読み書きできてしまう)
そこで多少"黒魔術"的ではあるしアクセス負荷が余計にかかるが、個人設定ページをスクレイピングしてapikeyを取得し使い捨てる方法を考えた。
これならクッキーにもWeb Storageにも残らず、個人ページをブラウザで開いてコピペするのと同じ処理になる。