RedmineのJavaScriptからRedmineの内部データを取得する方法の中で、authenticity_tokenを使う方法と、REST APIを使う方法を紹介する。
authenticity_tokenを使ったデータの取得
Redmine自身のフロントエンドが呼び出している機能を利用する。
各ページに埋め込まれているauthenticity_token
が必要。
authenticity_tokenの取得
authenticity_token
はRedmineの全てのページには埋め込まれているわけではない。
何かしらのデータ作成や更新の機能があるページに埋め込まれている模様。
$(':input[name="authenticity_token"]:first').val()
下記ページには埋め込まれているのを確認した。他にもあると思う。
- グローバルメニュー
- 「マイページ」
- 「プロジェクト」 > 新しいプロジェクト
- 「個人設定」
- プロジェクトメニュー
- 「概要」 > 新しいサブプロジェクト
- 「ロードマップ」
- 「リリース」 > 新しいリリース
- 「チケット」
- 「新しいチケット」
- 「Wiki」
- 「文書」
- 「ニュース」
- 「ファイル」 > 新しいファイル
- 「設定」
- 既存のチケット詳細
- 作業時間の記録
チケットに入力可能な値の一覧の取得
Redmine自身がチケット入力フォームを部分更新する際に使用しているupdate_form.js
を利用して、チケット入力フォームのHTMLと、HTMLをパースすることでチケットに入力可能なステータスなどの値を取得する。
ここで取得したhtmlIssueForm
をjQueryセレクターの第2引数に渡すことで、<input>
や<select>
に入力されているパラメータを抽出することも、このHTMLをそのまま利用して自前のチケット情報入力フォームのパーツに流用することもできる。
var project_identifier = "redmine-test";
var issue_id = '7'; // if create new issue, set blank.
$.post(
'/projects/' + project_identifier + '/issues/update_form.js' + (issue_id ? 'id=' + issue_id : ''),
{utf8:"✓", authenticity_token:$(':input[name="authenticity_token"]:first').val()}
).done(function(data){
eval(data.split("\n")[0].replace(/^replaceIssueFormWith\(/, 'var htmlIssueForm=').replace(/\);$/, ';'));
// デバッグ表示:HTMLフォーム
console.log(htmlIssueForm);
// デバッグ表示:入力項目の抽出
console.log($(":input", $(htmlIssueForm)));
});
解説すると少しトリッキーなことをしている。(Redmineのバージョンアップで死ぬ可能性がままある)
このレスポンス(data)にはチケット編集のHTMLフォームを置き換えるJavaScriptコードが含まれる。
このJavaScriptの本来の使われ方は、例えばトラッカーが変化するとトラッカーごとに入力フォームの入力項目が変わったり、ユーザーのロールによって選択可能なステータスが変わるなどのリアルタイムなHTMLフォームの変化に用いられている。
上記の処理はそのHTMLフォームの置き換えコードを正規表現で無理矢理に変数htmlIssueForm
への代入に変更してeval()実行している。
これにより置き換えに使われるはずだったHTMLがアクセス可能な変数htmlIssueForm
に代入される。
REST APIを使ったデータの取得
JavaScriptからREST APIでよく取得したくなるデータを抜粋した。
ここでは取得方法のみを軽く書いたが、APIによっては新規作成も更新もできる。
詳細はリンクしているREST APIドキュメントを参照して欲しい。
またJavaScriptからREST APIを呼び出す記事は別途作成した。
RedmineのJavaScriptからREST APIを使用する
ログインユーザーのapikeyの取得
apikeyを取得するような関数は存在しないためログインユーザーの「個人設定」をスクレイピングして取得する。
(下記コードは、当然ながらRedmineのバージョンアップなどで動かなくなる可能性はある)
// Redmineの全バージョンに対応。
// 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();
});
プロジェクトデータの取得
プロジェクト
var apikey = '****************************************';
// プロジェクト一覧
$.ajax({
type: 'get',
url: '/projects.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
// プロジェクト詳細
var project_identifier = "redmine-test";
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
カテゴリー
var apikey = '****************************************';
var project_identifier = "redmine-test";
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/issue_categories.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
バージョン
var apikey = '****************************************';
var project_identifier = "redmine-test";
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/versions.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
Wiki
var apikey = '****************************************';
var project_identifier = "redmine-test";
// ページ一覧
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/wiki/index.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
// ページ詳細
var page_name = 'Wiki';
$.ajax({
type: 'get',
url: '/projects/' + project_identifier + '/wiki/' + page_name + '.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
チケットデータの取得
チケット
var apikey = '****************************************';
// チケット
$.ajax({
type: 'get',
url: '/issues.json',
headers: {'X-Redmine-API-Key': apikey},
data: {project_id:1, limit:100, include:'relations'},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
// ページ詳細
var issue_id = '15781';
$.ajax({
type: 'get',
url: '/issues/' + issue_id + '.json',
headers: {'X-Redmine-API-Key': apikey},
data: {include:'children,attachments,relations,changesets,journals,watchers'},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
関連するチケット
var apikey = '****************************************';
var issue_id = '16894';
$.ajax({
type: 'get',
url: '/issues/' + issue_id + '/relations.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
システム定義データの取得
トラッカー
var apikey = '****************************************';
$.ajax({
type: 'get',
url: '/trackers.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
チケットステータス
var apikey = '****************************************';
$.ajax({
type: 'get',
url: '/issue_statuses.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
列挙項目
var apikey = '****************************************';
$.ajax({
type: 'get',
url: '/enumerations/issue_priorities.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));
カスタムフィールド
Custom Fields - Redmine
※システム管理者のapikeyが必要
var apikey = '****************************************';
$.ajax({
type: 'get',
url: '/custom_fields.json',
headers: {'X-Redmine-API-Key': apikey},
dataType: 'json',
contentType: 'application/json',
}).done((json) => console.log(json));