UNPKG

cb10-sdk

Version:

Cybozu Office 10 SDK for Node.js

230 lines 10.9 kB
"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