ユーザー情報を一括で更新する
概要
年度の変わり目などに発生する組織変更で多数のユーザーを追加・変更する場面において、手作業で一人ずつ操作するのは非常に手間がかかります。Web APIを使用することで一括でデータを更新し、作業の手間を省くことができます。
また、必要な情報を揃えておけば、必要なタイミングで自動的に実行することも可能です。
利用場面
- 新入社員のアカウントをまとめて登録する
- 既存メンバーの所属組織をまとめて変更する
- 退職者のアカウントをまとめて削除する
使用するAPI
以下のAPIを使用します。
- ユーザーの追加
- ユーザーの変更
- ユーザーの削除
サンプルスクリプト
言語に合わせて以下のタブを選択し、参照してください。
- JavaScript
- C#
入力情報
上記のサンプルスクリプトで使用する追加・更新・削除用のアカウント情報ファイルを以下のリンク先から参照できます。
//======================================================================
// ユーザー情報を一括で更新する
//======================================================================
//======================================================================
// 外部ファイル(ライブラリ、他ファイル)のインクルード
//======================================================================
const https = require('https'); // HTTPS通信を利用する場合に設定する
const http = require('http'); // HTTP通信を利用する場合に設定する
const axios = require('axios');
const fs = require('fs');
//======================================================================
// 共通部の定義
//======================================================================
// APIを呼び出すURLを設定する
const baseURLString = 'http://yourserver/TimeTrackerNX/api';
// サーバースペックに合わせてウェイト時間を設定する
// 1分間に1500件程度の処理に収まるようするため、
// 目安として推奨スペックでは100ms程度とする
const requestWaitTime = 100; //単位:ms
//----------------------------------------------------------------------
// Web API間の処理待ち関数
//----------------------------------------------------------------------
async function wait(time){
const d1 = new Date();
while (true) {
const d2 = new Date();
if (d2 - d1 > time) {
break;
}
}
}
//======================================================================
// メイン処理
//======================================================================
main();
async function main(){
// 引数チェック
if (process.argv.length < 3){
return 'enter username and password';
}
const userName = process.argv[2];
var pass;
var authString; //ブロック内スコープから外に出すためvarで宣言(固定値)
// 引数でパスワードが未入力の場合は空白とみなす
if (process.argv.length > 3){
pass = process.argv[3];
} else {
pass = '';
}
// 認証情報を取得する
var sendUrl = baseURLString + '/auth/token';
try{
const { data } = await axios.post(
sendUrl,
{
loginName : userName,
password : pass
},
/*
// https通信時に使用する
httpsAgent : new https.Agent({
rejectUnauthorized: false
})
*/
);
authString = 'Bearer ' + data.token;
} catch (err) {
console.log(err);
}
// 以降のAPI通信で利用する送信ヘッダを作成する
const request = axios.create({
baseURL : baseURLString,
headers :{
'Authorization' : authString
},
/*
// https通信時に使用する
httpsAgent : new https.Agent({
rejectUnauthorized: false
})
*/
});
// 新規ユーザーの登録
// JSON形式のデータ(例:後述のnewUserData.json)を入力とする
var filepath = './newUserData.json';
var changeMemberData = JSON.parse(fs.readFileSync(filepath, {encoding: "utf-8"}));
var sendUrl = '/system/users';
// JSON形式のユーザー情報からユーザー一人分の情報を取り出す
for (key in changeMemberData){
var userId;
// 新規ユーザーを追加するAPIを設定
sendUrl = '/system/users';
// ユーザー登録 (リクエストに1名分のユーザー情報を設定して送信)
try {
const { data } = await request.post(
sendUrl,
{
name : changeMemberData[key].name,
loginName : changeMemberData[key].loginName,
organization : changeMemberData[key].organization,
systemRole : changeMemberData[key].systemRole,
password : changeMemberData[key].password,
passwordConfirm : changeMemberData[key].passwordConfirm
}
);
// 戻り値のユーザーIDを取得(この後の休憩時間の設定に利用)
userId = data.id;
} catch (e) {
console.log(e);
}
//休憩時間を設定する。
sendUrl = '/api/system/users/' + userId + '/preference';
try {
const { data } = await request.put(
sendUrl,
{
breakTimes: [{
startTime :"12:00",
endTime :"13:00"
}]
}
);
} catch (e) {
console.log(e);
}
// 追加したユーザーをプロジェクト(全社活動など)のメンバーに設定
const newProjectId = '9,20,21';
sendUrl = '/project/projects/' + newProjectId;
// プロジェクトメンバーの追加(リクエストに新規ユーザーの情報を設定して送信)
try {
const { data } = await request.put(
sendUrl,
{
memberChange:{
adds : [{
partyId : userId,
partyType : 'User',
unitCost : 1000
}]
}
}
);
} catch (e) {
console.log(e);
}
await wait(requestWaitTime);
}
// 既存ユーザーの更新
// JSON形式のデータ(例:後述のupdateUserData.json)を入力とする
filepath = './updateUserData.json';
changeMemberData = JSON.parse(fs.readFileSync(filepath, {encoding: "utf-8"}));
// JSON形式のユーザー情報からユーザ ー一人分の情報を取り出す
for (key in changeMemberData){
var userId;
// 既存ユーザーの情報を取得するAPIを設定
sendUrl = '/system/users';
// ユーザーを一意に特定できる情報(コード)をもとに更新対象ユーザーのIDを取得
try {
const { data } = await request.get(
sendUrl,
{
params : {
code : changeMemberData[key].code
}
}
);
userId = data.data[0].id;
} catch (e) {
console.log(e);
}
// 既存ユーザーの情報を更新するAPIを設定
sendUrl = '/system/users/' + userId;
// ユーザー更新 (リクエストに1名分のユーザー情報を設定して送信)
try {
const { data } = await request.put(
sendUrl,
{
systemRole : changeMemberData[key].systemRole,
unitCost : changeMemberData[key].unitCost,
unitCostAppliedStartDate : changeMemberData[key].unitCostAppliedStartDate
}
);
} catch (e) {
console.log(e);
}
await wait(requestWaitTime);
}
//既存ユーザーの削除
// JSON形式のデータ(例:後述のdeleteUserData.json)を入力とする
filepath = './deleteUserData.json';
changeMemberData = JSON.parse(fs.readFileSync(filepath, {encoding: "utf-8"}));
// JSON形式のユーザー情報からユーザー一人分の情報を取り出す
for (key in changeMemberData){
var userId;
// 既存ユーザーの情報を取得するAPIを設定
sendUrl = '/system/users';
// ユーザーを一意に特定できる情報(コード)をもとに削除対象ユーザーのIDを取得
try {
const { data } = await request.get(
sendUrl,
{
params: {
code :changeMemberData[key].code
}
}
);
userId = data.data[0].id;
} catch (e) {
console.log(e);
}
// 既存ユーザーの情報を削除するAPIを設定
sendUrl = '/system/users/' + userId;
// ユーザー削除
try {
const { data } = await request.delete(
sendUrl
);
} catch (e) {
console.log(e);
}
await wait(requestWaitTime);
}
}
入力情報
上記のサンプルスクリプトで使用する追加・更新・削除用のアカウント情報ファイルを以下のリンク先から参照できます。
private async void main(object sender, EventArgs e)
{
//======================================================//
// 共通変数の定義・トークン取得処理 //
//======================================================//
JavaScriptSerializer serializar = new JavaScriptSerializer();
var httpClient = new HttpClient();
string serverUrl = "http://[ServerName]/TimeTrackerNX/";
string loginname = "okamoto";
string password = "";
string userId = null;
// トークンの取得
var tokenRequest = new Dictionary<string, string>
{
{"loginName",loginname },
{"password",password }
};
var jsonData = serializar.Serialize(tokenRequest);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
string requestUrl = serverUrl + "/api/auth/token";
var response = await httpClient.PostAsync(requestUrl, content);
string responseData = await response.Content.ReadAsStringAsync();
Token token;
try
{
token = serializar.Deserialize<Token>(responseData);
}
catch
{
MessageBox.Show("トークン取得に失敗しました。\n接続先のサーバーURL、ログイン名、パスワードを確認してください。");
return;
}
// ヘッダ設定
httpClient.DefaultRequestHeaders.Add("contentType", "application/json");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token.token);
//==========================================//
// 新規ユーザーの追加 //
//==========================================//
// 要素数 6 (name / loginName / organization / systemRole / password / passwordConfirm)
const int AddUserDataMemberNum = 6;
//------------------------------------------//
// CSVを入力にデータを取得 //
//------------------------------------------//
String[] newMemberData = null;
List<string> lists = new List<string>();
StreamReader sr = new StreamReader(@"newUserData.csv", System.Text.Encoding.GetEncoding("shift_jis"));
{
//タイトル行の回避(1行目はデータにしない)
string line = sr.ReadLine();
while (!sr.EndOfStream)
{
line = sr.ReadLine();
newMemberData = line.Split(',');
lists.AddRange(newMemberData);
}
}
//------------------------------------------//
// ユーザー自体を追加 //
//------------------------------------------//
for (int i = 0; i < lists.Count; i = i + AddUserDataMemberNum)
{
var Member = new Dictionary<string, string>
{
{"name",lists[i]},
{"loginName",lists[i+1]},
{"organization",lists[i+2]},
{"systemRole",lists[i+3] },
{"password",lists[i+4]},
{"passwordConfirm",lists[i+5]}
};
// ユーザー追加処理
requestUrl = serverUrl + "/api/system/users";
jsonData = serializar.Serialize(Member);
content = new StringContent(jsonData, Encoding.UTF8, "application/json");
response = await httpClient.PostAsync(requestUrl, content);
responseData = await response.Content.ReadAsStringAsync();
ResponseUser responseUser = new ResponseUser();
responseUser = serializar.Deserialize<ResponseUser>(responseData);
userId = responseUser.id;
//------------------------------------------//
// プロジェクトメンバーへ追加 //
//------------------------------------------//
string addProjectId = "6"; // 追加対象のプロジェクトIDを設定
requestUrl = serverUrl + "/api/project/projects/" + addProjectId;
MemberAdd addUser = new MemberAdd(userId);
MemberAdd[] addUsers = new MemberAdd[1];
addUsers[0] = addUser;
MemberChange memberChange = new MemberChange(addUsers, null, null, null);
var request = new Dictionary<string, MemberChange>
{
{"memberChange",memberChange}
};
jsonData = serializar.Serialize(request);
content = new StringContent(jsonData, Encoding.UTF8, "application/json");
response = await httpClient.PutAsync(requestUrl, content);
responseData = await response.Content.ReadAsStringAsync();
}
//==========================================//
// 既存ユーザーの情報更新 //
//==========================================//
String[] updateMemberData = null;
List<string> updatelists = new List<string>();
// 要素数 5 (name / code / systemRole / unitCost / unitCostAppliedStartDate)
const int UpdateUserDataMemberNum = 5;
//------------------------------------------//
// CSVを入力にデータを取得 //
//------------------------------------------//
sr = new StreamReader(@"updateUserData.csv", System.Text.Encoding.GetEncoding("shift_jis"));
{
//タイトル行の回避(1行目はデータにしない)
string line = sr.ReadLine();
while (!sr.EndOfStream)
{
line = sr.ReadLine();
updateMemberData = line.Split(',');
updatelists.AddRange(updateMemberData);
}
}
for (int i = 0; i < updatelists.Count; i = i + UpdateUserDataMemberNum)
{
var UpdateMember = new Dictionary<string, string>
{
{"name",updatelists[i]},
{"code",updatelists[i+1]},
{"systemRole",updatelists[i+2]},
{"unitCost",updatelists[i+3]},
{"unitCostAppliedStartDate",updatelists[i+4]}
};
//------------------------------------------//
// ユーザーIDの特定 //
// 注)コードが一意であることを前提 //
//------------------------------------------//
requestUrl = serverUrl + "/api/system/users?code=" + updatelists[i + 1];
response = await httpClient.GetAsync(requestUrl);
responseData = await response.Content.ReadAsStringAsync();
var updateUser = serializar.Deserialize<ResponseUsers>(responseData);
userId = updateUser.data[0].id;
//------------------------------------------//
// システムロール・コスト単価・変更日設定 //
//------------------------------------------//
requestUrl = serverUrl + "/api/system/users/" + userId;
jsonData = serializar.Serialize(UpdateMember);
content = new StringContent(jsonData, Encoding.UTF8, "application/json");
response = await httpClient.PutAsync(requestUrl, content);
responseData = await response.Content.ReadAsStringAsync();
}
//==========================================//
// ユーザーの削除 //
//==========================================//
String[] delMemberData = null;
List<string> dellists = new List<string>();
// 要素数 2 (name / code)
const int DelUserDataMemberNum = 2;
//------------------------------------------//
// CSVを入力にデータを取得 //
//------------------------------------------//
sr = new StreamReader(@"delUserData.csv", System.Text.Encoding.GetEncoding("shift_jis"));
{
//タイトル行の回避(1行目はデータにしない)
string line = sr.ReadLine();
while (!sr.EndOfStream)
{
line = sr.ReadLine();
delMemberData = line.Split(',');
dellists.AddRange(delMemberData);
}
}
for (int i = 0; i < dellists.Count; i = i + DelUserDataMemberNum)
{
var DelMember = new Dictionary<string, string>
{
{"name",dellists[i]},
{"code",dellists[i+1]}
};
//------------------------------------------//
// ユーザーIDの特定 //
//------------------------------------------//
requestUrl = serverUrl + "/api/system/users?code=" + dellists[i+1];
response = await httpClient.GetAsync(requestUrl);
responseData = await response.Content.ReadAsStringAsync();
var delUser = serializar.Deserialize<ResponseUsers>(responseData);
userId = delUser.data[0].id;
//------------------------------------------//
// ユーザーの削除処理 //
//------------------------------------------//
requestUrl = serverUrl + "/api/system/users/"+userId;
response = await httpClient.DeleteAsync(requestUrl);
}
}
}
// Tokenレスポンス用のクラス
public class Token
{
public string token { get; set; }
}
public class ResponseUser
{
public string isDeleted;
public string createdAt;
public string updatedAt;
public string createdBy;
public string updatedBy;
public string id;
public ResponseUser()
{
this.id = null;
}
}
public class ResponseUsers {
public string totalCount;
public ResponseUser[] data;
}
public class MemberAdd
{
public string partyId;
public string partyType;
public double unitCost;
public MemberAdd (string partyId)
{
this.partyId = partyId;
this.partyType = "User";
this.unitCost = 3000;
}
}
public class MemberUpdate
{
public string users;
public string ids;
public double unitCost;
public bool restore;
}
public class MemberChange
{
public MemberAdd[] adds;
public MemberUpdate[] updates;
public string removes;
public string removeUsers;
public MemberChange(MemberAdd[] adds, MemberUpdate[] updates, string removes, string removeUsers)
{
this.adds = adds;
this.updates = updates;
this.removes = removes;
this.removeUsers = removeUsers;
}
}