cb10-sdk
Version:
Cybozu Office 10 SDK for Node.js
230 lines • 10.9 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _Transport_instances, _a, _Transport_axiosInstance, _Transport_sendRequest, _Transport_createURLParams, _Transport_buildRequestConfig, _Transport_validateResponse, _Transport_appendCsrfTicket, _Transport_initializeSession, _Transport_performLogin, _Transport_buildLoginBody, _Transport_extractSessionCookie, _Transport_fetchCsrfTicket;
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
const Constants_1 = require("./Constants");
const Errors_1 = require("./Errors");
/**
* Cybozu Office 10 APIへのアクセスを管理するクラス
*
* このクラスはCybozu Office 10のHTTP APIへのアクセスを簡素化します。
* セッション管理、認証、CSRFトークンの処理を自動的に行います。
*
*/
class Transport {
get sessionCredentials() {
return this.options.sessionCredentials;
}
/**
* Transportクラスのインスタンスを作成します
*
* @param baseUrl - サイボウズのベースURL(http~/ag.cgiまで)
* @param accountId - ログインID
* @param password - パスワード
* @param cookie - 有効な既存のクッキー(オプション)
*
* @throws {CybozuOfficeSDKException} 認証に失敗した場合
*/
constructor(options) {
_Transport_instances.add(this);
this.options = options;
_Transport_axiosInstance.set(this, void 0);
const axiosConfig = {
...(options.axiosRequestConfig || {}),
baseURL: this.options.baseUrl,
maxRedirects: 0,
validateStatus: status => {
return status === 200 || status === 302;
},
};
__classPrivateFieldSet(this, _Transport_axiosInstance, axios_1.default.create(axiosConfig), "f");
}
/**
* GETリクエストを実行します
*
* @param options - GETリクエストのオプション
* @returns 取得したコンテンツ
*
* @throws {CybozuOfficeSDKException} リクエストが失敗した場合
*/
async get(options = {}) {
const { path, query, responseType = 'text', encoding = 'utf-8' } = options;
const response = await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_sendRequest).call(this, {
method: 'GET',
path,
query,
ensuresLoggedIn: true,
});
if (responseType === 'file') {
return Buffer.from(response.data).toString(encoding).trim();
}
return response.data;
}
/**
* POSTリクエストを実行します
*
* @param body - POSTリクエストのボディ
* @throws {CybozuOfficeSDKException} リクエストが失敗した場合
*/
async post(body) {
await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_sendRequest).call(this, {
method: 'POST',
contentType: Constants_1.ContentType.FORM_URLENCODED,
body,
ensuresLoggedIn: true,
});
}
}
_a = Transport, _Transport_axiosInstance = new WeakMap(), _Transport_instances = new WeakSet(), _Transport_sendRequest =
/**
* HTTPリクエストを実行します
*
* @param options - リクエストオプション
* @returns axiosのレスポンス
*/
async function _Transport_sendRequest(options) {
// ログイン済みが前提のリクエストの場合、 Cookie が未取得であれば Cookie を取得する
if (options.ensuresLoggedIn && !this.options.sessionCredentials) {
await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_initializeSession).call(this);
}
// ログイン済みが前提の POST リクエストの場合、 CSRF トークンを取得する
if (options.ensuresLoggedIn && !this.options.sessionCredentials?.csrfTicket && options.method === 'POST') {
this.options.sessionCredentials.csrfTicket = await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_fetchCsrfTicket).call(this);
}
const requestConfig = __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_buildRequestConfig).call(this, options);
if (options.query) {
requestConfig.params = __classPrivateFieldGet(_a, _a, "m", _Transport_createURLParams).call(_a, options.query);
}
const response = await __classPrivateFieldGet(this, _Transport_axiosInstance, "f").request(requestConfig);
__classPrivateFieldGet(_a, _a, "m", _Transport_validateResponse).call(_a, response);
const needsLogin = response.headers['x-cybozulogin'] === '1';
if (!options.preventSessionRefresh && needsLogin) {
await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_initializeSession).call(this);
return __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_sendRequest).call(this, { preventSessionRefresh: true, ...options });
}
return response;
}, _Transport_createURLParams = function _Transport_createURLParams(params) {
return new URLSearchParams(Object.entries(params).flatMap(([key, value]) => {
if (Array.isArray(value)) {
return value.map(v => [key, String(v)]);
}
return [[key, String(value)]];
}));
}, _Transport_buildRequestConfig = function _Transport_buildRequestConfig(options) {
const headers = {
Cookie: this.options.sessionCredentials?.cookie || '',
};
if (options.contentType) {
headers['Content-Type'] = options.contentType;
}
const config = {
method: options.method,
headers,
responseType: 'arraybuffer',
};
if (options.query) {
config.params = __classPrivateFieldGet(_a, _a, "m", _Transport_createURLParams).call(_a, options.query);
}
if (options.body) {
__classPrivateFieldGet(this, _Transport_instances, "m", _Transport_appendCsrfTicket).call(this, options.body);
config.data = __classPrivateFieldGet(_a, _a, "m", _Transport_createURLParams).call(_a, options.body);
}
return config;
}, _Transport_validateResponse = function _Transport_validateResponse(response) {
const cybozuError = response.headers['x-cybozu-error'];
if (cybozuError) {
throw new Errors_1.CybozuOfficeSDKException(cybozuError);
}
}, _Transport_appendCsrfTicket = function _Transport_appendCsrfTicket(body) {
if (this.options.sessionCredentials?.csrfTicket) {
body.csrf_ticket = this.options.sessionCredentials.csrfTicket;
}
}, _Transport_initializeSession =
/**
* セッションを初期化します
*
* @throws {CybozuOfficeSDKException} 認証に失敗した場合
*/
async function _Transport_initializeSession() {
const loginResponse = await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_performLogin).call(this);
const cookieValue = __classPrivateFieldGet(_a, _a, "m", _Transport_extractSessionCookie).call(_a, loginResponse);
this.options.sessionCredentials = {
cookie: cookieValue,
myOwnUID: Number(loginResponse.headers['x-cybozu-user']),
};
}, _Transport_performLogin =
/**
* ログインリクエストを実行します
*
* @returns ログインレスポンス
* @throws {CybozuOfficeSDKException} ログインに失敗した場合
*/
async function _Transport_performLogin() {
const response = await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_sendRequest).call(this, {
method: 'POST',
contentType: Constants_1.ContentType.FORM_URLENCODED,
body: __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_buildLoginBody).call(this),
ensuresLoggedIn: false,
});
return response;
}, _Transport_buildLoginBody = function _Transport_buildLoginBody() {
const body = {
Password: this.options.password,
_System: 'login',
_Login: '1',
};
if (this.options.id) {
body._ID = this.options.id;
}
else if (this.options.accountId) {
body._Account = this.options.accountId;
}
return body;
}, _Transport_extractSessionCookie = function _Transport_extractSessionCookie(response) {
const setCookie = response.headers['set-cookie'];
if (!setCookie || !Array.isArray(setCookie) || setCookie.length === 0) {
throw new Errors_1.CybozuOfficeSDKException('Failed to get session cookie');
}
const AGSESSID_REGEX = /(AGSESSID=.*?);/i;
const match = setCookie.filter(cookie => AGSESSID_REGEX.test(cookie)).map(cookie => AGSESSID_REGEX.exec(cookie));
if (!match || !match[0]) {
throw new Errors_1.CybozuOfficeSDKException('Failed to extract AGSESSID');
}
return match[0][1];
}, _Transport_fetchCsrfTicket =
/**
* CSRFトークンを取得します
*
* @returns CSRFトークン文字列
* @throws {CybozuOfficeSDKException} トークンの取得に失敗した場合
*/
async function _Transport_fetchCsrfTicket() {
const response = await __classPrivateFieldGet(this, _Transport_instances, "m", _Transport_sendRequest).call(this, {
// 「ファイルの追加」ページは HTML のファイルサイズが小さく、かつ、CSRF トークンが取得できるため利用
query: { page: 'FileAdd' },
method: 'GET',
ensuresLoggedIn: false,
});
const page = response.data.toString();
const match = /<input type="hidden" name="csrf_ticket" value="(.*?)">/i.exec(page);
if (!match) {
throw new Errors_1.CybozuOfficeSDKException('Failed to extract CSRF ticket');
}
return match[1];
};
exports.default = Transport;
//# sourceMappingURL=Transport.js.map