95 lines
3.5 KiB
JavaScript
95 lines
3.5 KiB
JavaScript
"use strict";
|
|
|
|
/*
|
|
* User Account認証(OAuth 2.0 認可コードフロー)の一回限りのセットアップスクリプト。
|
|
* Drive/共有ドライブAPIはService Account認証では利用できないため、実ユーザーの
|
|
* 認可を一度だけ行い、refresh_tokenを.envに保存する。以降のbackup.js実行は
|
|
* このrefresh_tokenからaccess_tokenを自動再発行する(ユーザー操作不要)。
|
|
*
|
|
* 事前準備:
|
|
* Developer Consoleの「User Account認証」欄の Redirect URL に、
|
|
* .env の LW_REDIRECT_URI と完全一致する値を登録しておくこと。
|
|
*
|
|
* 使い方:
|
|
* node lineworks-authorize.js
|
|
*/
|
|
|
|
const crypto = require("crypto");
|
|
const readline = require("readline");
|
|
|
|
const { loadEnv, updateEnvValue } = require("./lib/env");
|
|
loadEnv();
|
|
|
|
const { buildAuthorizeUrl, exchangeCodeForToken } = require("./lib/lineworksUserAuth");
|
|
|
|
function prompt(question) {
|
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
return new Promise((resolve) => {
|
|
rl.question(question, (answer) => {
|
|
rl.close();
|
|
resolve(answer.trim());
|
|
});
|
|
});
|
|
}
|
|
|
|
// リダイレクト後のURL全体、または code の値そのものが貼り付けられるケースの両方に対応する。
|
|
function extractCode(input) {
|
|
if (input.includes("code=")) {
|
|
try {
|
|
const url = new URL(input);
|
|
const code = url.searchParams.get("code");
|
|
if (code) return code;
|
|
} catch (_err) {
|
|
const match = input.match(/[?&]code=([^&\s]+)/);
|
|
if (match) return decodeURIComponent(match[1]);
|
|
}
|
|
}
|
|
return input;
|
|
}
|
|
|
|
async function main() {
|
|
const state = crypto.randomBytes(16).toString("hex");
|
|
const authorizeUrl = buildAuthorizeUrl({ state });
|
|
|
|
console.log("以下のURLをブラウザで開き、対象のLINE WORKSアカウントでログイン・同意してください:");
|
|
console.log("");
|
|
console.log(authorizeUrl);
|
|
console.log("");
|
|
console.log("同意後、Redirect URLへ遷移します(ページ自体が表示されなくても問題ありません)。");
|
|
console.log("遷移後のブラウザのアドレスバーのURL全体(または code= の値だけ)をコピーしてください。");
|
|
console.log("");
|
|
|
|
const input = await prompt("リダイレクト後のURL(またはcode)を貼り付けてEnter: ");
|
|
const code = extractCode(input);
|
|
|
|
if (!code) {
|
|
console.error("codeを取得できませんでした。");
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
console.log("アクセストークンに交換しています...");
|
|
const tokenData = await exchangeCodeForToken(code);
|
|
|
|
if (!tokenData.refresh_token) {
|
|
console.error("レスポンスに refresh_token が含まれていませんでした。");
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
updateEnvValue("LW_USER_REFRESH_TOKEN", tokenData.refresh_token);
|
|
|
|
console.log("");
|
|
console.log("成功しました。");
|
|
console.log(` scope: ${tokenData.scope}`);
|
|
console.log(` access_tokenの有効期限: ${tokenData.expires_in}秒`);
|
|
console.log(" refresh_token を .env の LW_USER_REFRESH_TOKEN に保存しました。");
|
|
console.log("");
|
|
console.log("これで 'node backup.js run' が共有ドライブへアクセスできるようになります。");
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(`セットアップに失敗しました: ${err.message}`);
|
|
process.exitCode = 1;
|
|
});
|