LANG SELRCT

コードを書く場所

2019年3月1日金曜日

JIRAのAPIでemailからaccountIdを取得したい


JIRA APIのusernameが廃止になるため、代わりにaccountIdを使う方法を調べました。


知りたかったのはEmailからaccountIdを取得するこれ


https://SITENAME.atlassian.net/rest/api/3/user/assignable/search?project=PROJECT_KEY&query=EMAIL


※SITENAME、PROJECT_KEY、EMAILを指定すると結果が配列で返ってきます。


これは以下の公式ガイドのFind userのUpdated requestにありました。
https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/#updated-request-1
Updated request
You will need to update your code to use a method that supports the query request parameter, where the value can be an email address, display name, or any other user attribute.
GET https://your-domain.atlassian.net/rest/api/3/user/assignable/search?project=ABC&query=your-user-attribute
Email以外にdisplay nameなどでも取得できるようです。

指定したEmailの結果が「配列で返ってくる」という点が一癖ある感じでした。

実際にやってみた手順を以下に書き残しておきます。


試してみる


foo@gmail.com を渡して結果を取得してみる

JIRAにログインしている状態で、ブラウザのアドレスバーに以下を入力します。
https://SITENAME.atlassian.net/rest/api/3/user/assignable/search?project=PROJECT_KEY&query=foo@gmail.com

  • SITENAMEは利用している名前
  • PROJECT_KEYは対象のプロジェクト
  • foo@gmail.comは自分のEmail

該当のユーザが1人の場合は以下のように返ってきます。
IDが今回取得したいaccountIdです。
[{
    "self": "https://SITENAME.atlassian.net/rest/api/3/user?accountId=ID",
    "key": "admin",
    "accountId": "ID",
    "name": "admin",
    "emailAddress": "foo@gmail.com",
    "avatarUrls": {
        "16x16": "URL",
        "24x24": "URL",
        "32x32": "URL",
        "48x48": "URL"
    },
    "displayName": "NAME",
    "active": true,
    "timeZone": "Asia/Tokyo",
    "locale": "en_US"
}]


もし foo@gmail.comとは別に、bar.foo@gmail.com のようなユーザがいる場合は、「foo@gmail.com」という文字列が一致して以下のように2つのアカウント情報が返ってきます。
(渡したEmailに完全一致するものだけが返ってくると思ったらそうではない)
[{
    "self": "https://SITENAME.atlassian.net/rest/api/3/user?accountId=ID",
    "key": "admin",
    "accountId": "ID",
    "name": "admin",
    "emailAddress": "foo@gmail.com",
    "avatarUrls": {
      "16x16": "URL",
      "24x24": "URL",
      "32x32": "URL",
      "48x48": "URL"
    },
    "displayName": "NAME",
    "active": true,
    "timeZone": "Asia/Tokyo",
    "locale": "en_US"
  },
  {
    "self": "https://SITENAME.atlassian.net/rest/api/3/user?accountId=ID",
    "key": "admin",
    "accountId": "ID",
    "name": "admin",
    "emailAddress": "bar.foo@gmail.com",
    "avatarUrls": {
      "16x16": "URL",
      "24x24": "URL",
      "32x32": "URL",
      "48x48": "URL"
    },
    "displayName": "NAME",
    "active": true,
    "timeZone": "Asia/Tokyo",
    "locale": "en_US"
  }
]

上記の結果からaccountIdを取得しますが、配列で返ってくるため、emailAddressが一致するアカウントを特定してaccountIdを取得します。


以下2つのパターンのコードを書きました。
  • emailからaccountIdを取得するコード
  • accountIdをreporterに入れて課題を作成するコード


emailからaccountIdを取得するコード


コード.gs
function getToken() {
  var id = "EMAIL";
  var api_token = "API Token";
  var token = Utilities.base64Encode(id + ":" + api_token);
  return token;
}

function getAccountId() {
  var project = 'KEY';//プロジェクトを指定する
  var email = Session.getActiveUser().getEmail();
  var url = 'https://SITENAME.atlassian.net/rest/api/3/user/assignable/search?project=' + project + '&query=' + email;
    var options = {
    method: "get",
    contentType: "application/json",
    headers: {"Authorization": " Basic " + getToken()}
  }
  var response = UrlFetchApp.fetch(url, options);
  var jobj = JSON.parse(response);
  var accountInfo = getAccountInfo(jobj, email);
  var accountId = accountInfo['accountId'];
  Logger.log(accountId);
}

function getAccountInfo(jobj, email) {
  var accountInfo;
  for(var i = 0; i < jobj.length; i++) {
    var emailAddress = jobj[i]['emailAddress'];
    if(emailAddress === email) {
      accountInfo = jobj[i];
    }
  }
  return accountInfo;
} 

意訳
この機能がやること
ログインEmail
API Token
base64でエンコードして
返す


この機能がやること
プロジェクトを指定する
アクティブユーザのEmailを取得する
APIにアクセスしてパラメータを渡す
optionsを作る
methodを設定
contentTypeを設定
headersを設定
  }
APIにアクセスして結果を取得する
結果をオブジェクトに変換する
getAccountInfo()にjobjとemailを渡して結果を得る
その中からaccountIdを取得して
ログに出す


この機能がやること
accountInfoの入れ物を作る
渡されたjobjの要素の数だけ繰り返す
ひとつずつemailAddressを取得して
渡されたemailと一致したら
accountInfoにそのアカウント情報を入れる


accountInfoを返す




ログに出したresponseの中身を見てみる
[
    [{
        "self": "https://SITENAME.atlassian.net/rest/api/3/user?accountId=ここにIDが書かれている",
        "key": "admin",
        "accountId": "ここにもIDが書かれている",
        "name": "admin",
        "emailAddress": "自分のEMAIL",
        "avatarUrls": {
            "16x16": "URL",
            "24x24": "URL",
            "32x32": "URL",
            "48x48": "URL"
        },
        "displayName": "YOUR NAME",
        "active": true,
        "timeZone": "Asia/Tokyo",
        "locale": "en_US"
    }], ここにaccountIdを抜き出す
]


accountIdをreporterに入れて課題を作成するコード


コード2.gs
var BASE_URL = 'https://SITENAME.atlassian.net';
var ISSUE_URL = BASE_URL + '/rest/api/3/issue/';

function getToken() {
  var id = "EMAIL";
  var api_token = "API Token";
  var token = Utilities.base64Encode(id + ":" + api_token);
  return token;
}

function doPost() {
  var token = getToken();
  var payload = getPayload();
  var options = getOptions(token, payload);
  var response = UrlFetchApp.fetch(ISSUE_URL, options);
  Logger.log(response);
  var key = getKey(response);
  Logger.log(key);
}

function getPayload(values) {
  var email = Session.getActiveUser().getEmail();
  var data = {
    project: {key: "KEY"},
    issuetype: {name: "Bug"},
    summary: "たいとる",
    description: ["タスクの説明です\n説明の2行め"],
    reporter: {id: getAccountId()}
  };
  var fields = {fields: data};
  var payload = JSON.stringify(fields);
  return payload;
}

function getOptions(token, payload) {
  var options = {
    method: "post",
    payload: payload,
    contentType: "application/json",
    headers: {"Authorization": " Basic " + token}
  }
  return options;
}

function getKey(response){
  var jobj = JSON.parse(response);
  var key = jobj["key"];
  return key;
}

function getAccountId() {
  var project = 'KEY';//プロジェクトを指定する
  var email = Session.getActiveUser().getEmail();
  var url = BASE_URL + '/rest/api/3/user/assignable/search?project=' + project + '&query=' + email;
    var options = {
    method: "get",
    contentType: "application/json",
    headers: {"Authorization": " Basic " + getToken()}
  }
  var response = UrlFetchApp.fetch(url, options);
  var jobj = JSON.parse(response);
  var accountInfo = getAccountInfo(jobj, email);
  var accountId = accountInfo['accountId'];
  Logger.log(accountId);
  return accountId;
}

function getAccountInfo(jobj, email) {
  var accountInfo;
  for(var i = 0; i < jobj.length; i++) {
    var emailAddress = jobj[i]['emailAddress'];
    if(emailAddress === email) {
      accountInfo = jobj[i];
    }
  }
  return accountInfo;
} 


補足:

APIを利用して課題を作成する際に、reporterの値がusernameだと今回の廃止の影響を受けるため、コード2.gsのようにaccountIdへ変更します。

今回やったこと
  1. emailからaccountIdを取得する方法を見つける
  2. reporterにaccountIdを入れて課題を作成する


注意点:
Users will be able to restrict the visibility of their personal data through their user profile privacy settings, or in the
case ofa managed account, the visibility settings that are decided by the site administrator.This means that fields such as email will only be returned by the API
if the user has permitted that data to be visible.Note that this means that some fields can be null
という仕様変更によって上記のコードではemailAddressの値を取得できなくなりました。
デフォルトでemailアドレスが非公開になっているため、以下のリンクを開いて「全員」に設定し直すと取得できるようになります。
https://id.atlassian.com/manage-profile/profile-and-visibility