dsh-cloudq 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/client.js +35 -110
- package/lib/index.js +33 -66
- package/package.json +1 -1
- package/skills/cloudq/scripts/login.py +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ dsh plugin --profile web remove dsh-cloudq
|
|
|
35
35
|
|
|
36
36
|
## 凭证配置
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
设置卡片支持配置腾讯云 `SecretId` 和 `SecretKey` 凭证。
|
|
39
39
|
|
|
40
40
|
- 凭证保存在本机 `~/.tencent-cloudq/credential.json`,文件权限仅允许当前用户访问。
|
|
41
41
|
- 敏感凭证通过标准输入传递给 Python 辅助脚本,不会放入命令行参数。
|
package/lib/client.js
CHANGED
|
@@ -100,6 +100,11 @@ window.__ModuleLoader__.load({
|
|
|
100
100
|
background: var(--dsw-alias-bg-layer-3, #fff);
|
|
101
101
|
color: var(--dsw-alias-label-primary, #17191c);
|
|
102
102
|
}
|
|
103
|
+
.dsh-cloudq-settings-card *,
|
|
104
|
+
.dsh-cloudq-settings-card *::before,
|
|
105
|
+
.dsh-cloudq-settings-card *::after {
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
}
|
|
103
108
|
.dsh-cloudq-settings-card__summary {
|
|
104
109
|
padding: 15px 16px;
|
|
105
110
|
}
|
|
@@ -215,10 +220,11 @@ window.__ModuleLoader__.load({
|
|
|
215
220
|
flex-wrap: wrap;
|
|
216
221
|
}
|
|
217
222
|
.dsh-cloudq-settings-card__actions--stacked {
|
|
218
|
-
flex-direction: column
|
|
223
|
+
flex-direction: column;
|
|
224
|
+
align-items: stretch;
|
|
219
225
|
}
|
|
220
226
|
.dsh-cloudq-settings-card__actions--stacked button {
|
|
221
|
-
|
|
227
|
+
align-self: flex-end;
|
|
222
228
|
}
|
|
223
229
|
.dsh-cloudq-settings-card__btn {
|
|
224
230
|
display: inline-flex;
|
|
@@ -1906,7 +1912,7 @@ display: none;
|
|
|
1906
1912
|
panelBody.textContent = "";
|
|
1907
1913
|
const err = document.createElement("div");
|
|
1908
1914
|
err.className = "dsh-cloudq-panel__error";
|
|
1909
|
-
err.textContent =
|
|
1915
|
+
err.textContent = cloudqPanelErrorText(error, "用量加载失败");
|
|
1910
1916
|
panelBody.appendChild(err);
|
|
1911
1917
|
});
|
|
1912
1918
|
}
|
|
@@ -2009,7 +2015,7 @@ display: none;
|
|
|
2009
2015
|
list.textContent = "";
|
|
2010
2016
|
const err = document.createElement("div");
|
|
2011
2017
|
err.className = "dsh-cloudq-panel__error";
|
|
2012
|
-
err.textContent =
|
|
2018
|
+
err.textContent = cloudqPanelErrorText(error, "灵感加载失败");
|
|
2013
2019
|
list.appendChild(err);
|
|
2014
2020
|
});
|
|
2015
2021
|
}
|
|
@@ -2152,7 +2158,7 @@ display: none;
|
|
|
2152
2158
|
panelBody.textContent = "";
|
|
2153
2159
|
const err = document.createElement("div");
|
|
2154
2160
|
err.className = "dsh-cloudq-panel__error";
|
|
2155
|
-
err.textContent =
|
|
2161
|
+
err.textContent = cloudqPanelErrorText(error, "制品加载失败");
|
|
2156
2162
|
panelBody.appendChild(err);
|
|
2157
2163
|
});
|
|
2158
2164
|
}
|
|
@@ -2433,7 +2439,7 @@ display: none;
|
|
|
2433
2439
|
summary.textContent = "加载失败";
|
|
2434
2440
|
const err = document.createElement("div");
|
|
2435
2441
|
err.className = "dsh-cloudq-panel__error";
|
|
2436
|
-
err.textContent =
|
|
2442
|
+
err.textContent = cloudqPanelErrorText(error, "架构图加载失败");
|
|
2437
2443
|
grid.appendChild(err);
|
|
2438
2444
|
});
|
|
2439
2445
|
};
|
|
@@ -2452,7 +2458,7 @@ display: none;
|
|
|
2452
2458
|
panelBody.textContent = "";
|
|
2453
2459
|
const err = document.createElement("div");
|
|
2454
2460
|
err.className = "dsh-cloudq-panel__error";
|
|
2455
|
-
err.textContent =
|
|
2461
|
+
err.textContent = cloudqPanelErrorText(error, "架构目录加载失败");
|
|
2456
2462
|
panelBody.appendChild(err);
|
|
2457
2463
|
});
|
|
2458
2464
|
}
|
|
@@ -2732,8 +2738,6 @@ display: none;
|
|
|
2732
2738
|
};
|
|
2733
2739
|
}
|
|
2734
2740
|
const API_CREDENTIAL = "/api/dsh-cloudq/credential";
|
|
2735
|
-
const API_LOGIN_URL = "/api/dsh-cloudq/login/url";
|
|
2736
|
-
const API_LOGIN_SAVE = "/api/dsh-cloudq/login/save";
|
|
2737
2741
|
const API_LOGOUT = "/api/dsh-cloudq/logout";
|
|
2738
2742
|
const API_CREDENTIAL_TEST = "/api/dsh-cloudq/credential/test";
|
|
2739
2743
|
const API_CREDENTIAL_SAVE = "/api/dsh-cloudq/credential/save";
|
|
@@ -2744,6 +2748,14 @@ display: none;
|
|
|
2744
2748
|
this.code = code;
|
|
2745
2749
|
}
|
|
2746
2750
|
};
|
|
2751
|
+
/**
|
|
2752
|
+
* Panel-facing error text. A missing credential gets an actionable pointer to
|
|
2753
|
+
* the settings card instead of a raw load failure message.
|
|
2754
|
+
*/
|
|
2755
|
+
function cloudqPanelErrorText(error, prefix) {
|
|
2756
|
+
if (error instanceof CloudQApiError && error.code === "NeedAuth") return "尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置后重试。";
|
|
2757
|
+
return `${prefix}:${error instanceof Error ? error.message : "未知错误"}`;
|
|
2758
|
+
}
|
|
2747
2759
|
async function cloudqRequest(url, init, timeoutMs = 2e4) {
|
|
2748
2760
|
const controller = new AbortController();
|
|
2749
2761
|
const timeout = window.setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -2788,9 +2800,8 @@ display: none;
|
|
|
2788
2800
|
const [loading, setLoading] = react.useState(true);
|
|
2789
2801
|
const [busy, setBusy] = react.useState();
|
|
2790
2802
|
const [status, setStatus] = react.useState();
|
|
2791
|
-
const [authorizeUrl, setAuthorizeUrl] = react.useState("");
|
|
2792
|
-
const [code, setCode] = react.useState("");
|
|
2793
2803
|
const [feedback, setFeedback] = react.useState();
|
|
2804
|
+
const [validated, setValidated] = react.useState(false);
|
|
2794
2805
|
const [secretId, setSecretId] = react.useState("");
|
|
2795
2806
|
const [secretKey, setSecretKey] = react.useState("");
|
|
2796
2807
|
const refresh = react.useCallback(async () => {
|
|
@@ -2810,61 +2821,13 @@ display: none;
|
|
|
2810
2821
|
react.useEffect(() => {
|
|
2811
2822
|
refresh();
|
|
2812
2823
|
}, [refresh]);
|
|
2813
|
-
const handleGetAuthorizeUrl = async () => {
|
|
2814
|
-
setBusy("url");
|
|
2815
|
-
setFeedback(void 0);
|
|
2816
|
-
try {
|
|
2817
|
-
const response = await cloudqRequest(API_LOGIN_URL, { method: "POST" });
|
|
2818
|
-
setAuthorizeUrl(response.authorize_url);
|
|
2819
|
-
if (response.authorize_url) window.open(response.authorize_url, "_blank", "noopener");
|
|
2820
|
-
} catch (error) {
|
|
2821
|
-
setFeedback({
|
|
2822
|
-
kind: "error",
|
|
2823
|
-
text: error.message
|
|
2824
|
-
});
|
|
2825
|
-
} finally {
|
|
2826
|
-
setBusy(void 0);
|
|
2827
|
-
}
|
|
2828
|
-
};
|
|
2829
|
-
const handleSaveCode = async () => {
|
|
2830
|
-
const trimmed = code.trim();
|
|
2831
|
-
if (!trimmed) {
|
|
2832
|
-
setFeedback({
|
|
2833
|
-
kind: "error",
|
|
2834
|
-
text: "请先在浏览器中完成授权,然后粘贴授权码。"
|
|
2835
|
-
});
|
|
2836
|
-
return;
|
|
2837
|
-
}
|
|
2838
|
-
setBusy("save");
|
|
2839
|
-
setFeedback(void 0);
|
|
2840
|
-
try {
|
|
2841
|
-
const response = await cloudqRequest(API_LOGIN_SAVE, {
|
|
2842
|
-
method: "POST",
|
|
2843
|
-
body: JSON.stringify({ code: trimmed })
|
|
2844
|
-
});
|
|
2845
|
-
setStatus(response.status);
|
|
2846
|
-
setCode("");
|
|
2847
|
-
setFeedback({
|
|
2848
|
-
kind: "success",
|
|
2849
|
-
text: "登录成功,凭证已保存。"
|
|
2850
|
-
});
|
|
2851
|
-
} catch (error) {
|
|
2852
|
-
setFeedback({
|
|
2853
|
-
kind: "error",
|
|
2854
|
-
text: error.message
|
|
2855
|
-
});
|
|
2856
|
-
} finally {
|
|
2857
|
-
setBusy(void 0);
|
|
2858
|
-
}
|
|
2859
|
-
};
|
|
2860
2824
|
const handleLogout = async () => {
|
|
2861
2825
|
setBusy("logout");
|
|
2862
2826
|
setFeedback(void 0);
|
|
2863
2827
|
try {
|
|
2864
2828
|
await cloudqRequest(API_LOGOUT, { method: "POST" });
|
|
2865
2829
|
setStatus({ logged_in: false });
|
|
2866
|
-
|
|
2867
|
-
setCode("");
|
|
2830
|
+
setValidated(false);
|
|
2868
2831
|
setFeedback({
|
|
2869
2832
|
kind: "success",
|
|
2870
2833
|
text: "已退出登录。"
|
|
@@ -2903,26 +2866,27 @@ display: none;
|
|
|
2903
2866
|
setSecretId("");
|
|
2904
2867
|
setSecretKey("");
|
|
2905
2868
|
}
|
|
2869
|
+
setValidated(true);
|
|
2906
2870
|
setFeedback({
|
|
2907
2871
|
kind: "success",
|
|
2908
2872
|
text: successText
|
|
2909
2873
|
});
|
|
2910
2874
|
} catch (error) {
|
|
2875
|
+
setValidated(false);
|
|
2876
|
+
const invalid = error instanceof CloudQApiError && error.code !== "network-error" && error.code !== "invalid-response";
|
|
2911
2877
|
setFeedback({
|
|
2912
2878
|
kind: "error",
|
|
2913
|
-
text: error.message
|
|
2879
|
+
text: invalid ? "AKSK 无效,请检查后重新配置。" : error.message
|
|
2914
2880
|
});
|
|
2915
2881
|
} finally {
|
|
2916
2882
|
setBusy(void 0);
|
|
2917
2883
|
}
|
|
2918
2884
|
};
|
|
2919
|
-
const handleTestConnection = () => submitAccessKey(API_CREDENTIAL_TEST, "test", "
|
|
2920
|
-
const handleSaveAccessKey = () => submitAccessKey(API_CREDENTIAL_SAVE, "save-ak", "
|
|
2885
|
+
const handleTestConnection = () => submitAccessKey(API_CREDENTIAL_TEST, "test", "连接成功,AKSK 有效。");
|
|
2886
|
+
const handleSaveAccessKey = () => submitAccessKey(API_CREDENTIAL_SAVE, "save-ak", "配置已保存,AKSK 有效。");
|
|
2921
2887
|
const loggedIn = status?.logged_in === true;
|
|
2922
|
-
const
|
|
2923
|
-
const
|
|
2924
|
-
const badgeText = expired ? "凭证已过期" : loggedIn ? "已登录" : "未登录";
|
|
2925
|
-
const summarySubtitle = loggedIn ? "腾讯云 CloudQ 凭证已激活,可直接使用 CloudQ 模式。" : "用于在 CloudQ 模式下调用腾讯云 SSE API 与 CLI 工具。";
|
|
2888
|
+
const akskValid = validated || loggedIn;
|
|
2889
|
+
const summarySubtitle = akskValid ? "腾讯云 CloudQ 凭证已激活,可直接使用 CloudQ 模式。" : "用于在 CloudQ 模式下调用腾讯云 SSE API 与 CLI 工具。";
|
|
2926
2890
|
const disabled = loading || busy !== void 0;
|
|
2927
2891
|
return react_jsx_runtime.jsx("section", {
|
|
2928
2892
|
className: "dsh-cloudq-settings-card",
|
|
@@ -2938,9 +2902,9 @@ display: none;
|
|
|
2938
2902
|
children: [react_jsx_runtime.jsx("strong", { children: "CloudQ" }), react_jsx_runtime.jsx("small", { children: summarySubtitle })]
|
|
2939
2903
|
}), react_jsx_runtime.jsx("span", {
|
|
2940
2904
|
className: "dsh-cloudq-settings-card__summary-right",
|
|
2941
|
-
children: [react_jsx_runtime.jsx("span", {
|
|
2942
|
-
className:
|
|
2943
|
-
children: [react_jsx_runtime.jsx("span", { className: "dsh-cloudq-settings-card__badge-dot" }),
|
|
2905
|
+
children: [akskValid && react_jsx_runtime.jsx("span", {
|
|
2906
|
+
className: "dsh-cloudq-settings-card__badge dsh-cloudq-settings-card__badge--ok",
|
|
2907
|
+
children: [react_jsx_runtime.jsx("span", { className: "dsh-cloudq-settings-card__badge-dot" }), "AKSK有效"]
|
|
2944
2908
|
}), react_jsx_runtime.jsx("span", {
|
|
2945
2909
|
className: `dsh-cloudq-settings-card__chevron${expanded ? " is-open" : ""}`,
|
|
2946
2910
|
children: "▾"
|
|
@@ -2952,20 +2916,10 @@ display: none;
|
|
|
2952
2916
|
children: [
|
|
2953
2917
|
loading ? react_jsx_runtime.jsx("div", {
|
|
2954
2918
|
className: "dsh-cloudq-settings-card__hint",
|
|
2955
|
-
children: "
|
|
2919
|
+
children: "正在检查凭证状态…"
|
|
2956
2920
|
}) : react_jsx_runtime.jsx("div", {
|
|
2957
2921
|
className: "dsh-cloudq-settings-card__rows",
|
|
2958
2922
|
children: [
|
|
2959
|
-
react_jsx_runtime.jsx("div", {
|
|
2960
|
-
className: "dsh-cloudq-settings-card__row",
|
|
2961
|
-
children: [react_jsx_runtime.jsx("span", {
|
|
2962
|
-
className: "dsh-cloudq-settings-card__row-key",
|
|
2963
|
-
children: "状态"
|
|
2964
|
-
}), react_jsx_runtime.jsx("span", {
|
|
2965
|
-
className: "dsh-cloudq-settings-card__row-val",
|
|
2966
|
-
children: badgeText
|
|
2967
|
-
})]
|
|
2968
|
-
}),
|
|
2969
2923
|
status?.credential_file ? react_jsx_runtime.jsx("div", {
|
|
2970
2924
|
className: "dsh-cloudq-settings-card__row",
|
|
2971
2925
|
children: [react_jsx_runtime.jsx("span", {
|
|
@@ -3023,35 +2977,6 @@ display: none;
|
|
|
3023
2977
|
children: feedback.text
|
|
3024
2978
|
}) : null,
|
|
3025
2979
|
!loggedIn && react_jsx_runtime.jsx("div", { children: [
|
|
3026
|
-
react_jsx_runtime.jsx("div", {
|
|
3027
|
-
className: "dsh-cloudq-settings-card__actions",
|
|
3028
|
-
children: [react_jsx_runtime.jsx("button", {
|
|
3029
|
-
type: "button",
|
|
3030
|
-
className: "dsh-cloudq-settings-card__btn dsh-cloudq-settings-card__btn--primary",
|
|
3031
|
-
disabled,
|
|
3032
|
-
onClick: handleGetAuthorizeUrl,
|
|
3033
|
-
children: busy === "url" ? "获取中…" : "获取授权链接"
|
|
3034
|
-
})]
|
|
3035
|
-
}),
|
|
3036
|
-
authorizeUrl && react_jsx_runtime.jsx("div", {
|
|
3037
|
-
className: "dsh-cloudq-settings-card__hint",
|
|
3038
|
-
children: "已在新标签页打开授权页。授权完成后,请将页面显示的授权码粘贴到下方:"
|
|
3039
|
-
}),
|
|
3040
|
-
react_jsx_runtime.jsx("div", {
|
|
3041
|
-
className: "dsh-cloudq-settings-card__actions dsh-cloudq-settings-card__actions--stacked",
|
|
3042
|
-
children: [react_jsx_runtime.jsx("input", {
|
|
3043
|
-
className: "dsh-cloudq-settings-card__input",
|
|
3044
|
-
placeholder: "粘贴授权码",
|
|
3045
|
-
value: code,
|
|
3046
|
-
onChange: (event) => setCode(event.target.value)
|
|
3047
|
-
}), react_jsx_runtime.jsx("button", {
|
|
3048
|
-
type: "button",
|
|
3049
|
-
className: "dsh-cloudq-settings-card__btn",
|
|
3050
|
-
disabled,
|
|
3051
|
-
onClick: handleSaveCode,
|
|
3052
|
-
children: busy === "save" ? "登录中…" : "完成登录"
|
|
3053
|
-
})]
|
|
3054
|
-
}),
|
|
3055
2980
|
react_jsx_runtime.jsx("div", {
|
|
3056
2981
|
className: "dsh-cloudq-settings-card__field",
|
|
3057
2982
|
children: [
|
package/lib/index.js
CHANGED
|
@@ -392,9 +392,9 @@ function runScript$1(scriptsDirectory, scriptName, args, { timeoutMs = 3e4, json
|
|
|
392
392
|
* and referenced through a directory `resourceBase`, so every `{baseDir}`
|
|
393
393
|
* placeholder in the body resolves against the installed package directory.
|
|
394
394
|
*
|
|
395
|
-
* It also exposes a small credential-management API (status /
|
|
396
|
-
* save
|
|
397
|
-
*
|
|
395
|
+
* It also exposes a small credential-management API (status / AK-SK test &
|
|
396
|
+
* save / logout) that the client half renders in the settings panel, so the
|
|
397
|
+
* CloudQ credential flow no longer requires touching a terminal.
|
|
398
398
|
*
|
|
399
399
|
* @module dsh-cloudq
|
|
400
400
|
*/
|
|
@@ -420,8 +420,13 @@ function renderedSkillContent() {
|
|
|
420
420
|
return rawSkillContent().replace(/\{baseDir\}/g, baseDir);
|
|
421
421
|
}
|
|
422
422
|
/** Run one helper from the bundled CloudQ skill. */
|
|
423
|
-
function runScript(scriptName, args, options) {
|
|
424
|
-
|
|
423
|
+
async function runScript(scriptName, args, options) {
|
|
424
|
+
try {
|
|
425
|
+
return await runScript$1(resolve(skillDirectory(), "scripts"), scriptName, args, options);
|
|
426
|
+
} catch (error) {
|
|
427
|
+
if (error instanceof HttpError && error.code === "NeedAuth") throw new HttpError(401, "NeedAuth", "尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置。");
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
425
430
|
}
|
|
426
431
|
/** Remove host filesystem details before returning credential state to the browser. */
|
|
427
432
|
function publicCredentialStatus(status) {
|
|
@@ -434,15 +439,6 @@ function publicCredentialStatus(status) {
|
|
|
434
439
|
async function credentialStatus() {
|
|
435
440
|
return publicCredentialStatus(await runScript("login.py", ["--status"]));
|
|
436
441
|
}
|
|
437
|
-
function authorizeUrl() {
|
|
438
|
-
return runScript("login.py", ["--authorize-url"]);
|
|
439
|
-
}
|
|
440
|
-
async function saveAuthCode(code) {
|
|
441
|
-
return publicCredentialStatus(await runScript("login.py", ["--save", "--stdin"], {
|
|
442
|
-
stdin: JSON.stringify({ code }),
|
|
443
|
-
sensitiveValues: [code]
|
|
444
|
-
}));
|
|
445
|
-
}
|
|
446
442
|
function logout() {
|
|
447
443
|
return runScript("logout.py", [], { jsonOnly: false });
|
|
448
444
|
}
|
|
@@ -616,23 +612,29 @@ const inject = [
|
|
|
616
612
|
"sessionQuery"
|
|
617
613
|
];
|
|
618
614
|
function apply(ctx) {
|
|
619
|
-
ctx.effect(() =>
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
615
|
+
ctx.effect(() => {
|
|
616
|
+
ctx.settings.register(SETTINGS_NAMESPACE, Config, { base: {} });
|
|
617
|
+
}, "dsh-cloudq: settings namespace");
|
|
618
|
+
ctx.effect(() => {
|
|
619
|
+
ctx.settings.register(PLUGIN_MANAGER_NAMESPACE, Config, { base: {} });
|
|
620
|
+
}, "dsh-cloudq: plugin-manager settings namespace");
|
|
621
|
+
ctx.effect(() => {
|
|
622
|
+
ctx.skills.register({
|
|
623
|
+
name: "cloudq",
|
|
624
|
+
description: "用户咨询腾讯云产品资源、AWS、阿里云等多云资源时,查看智能顾问架构图、架构目录、架构详情、架构评估结果、绘制架构图、开通智能顾问时、AI智能巡检、AI容量监测、AI混沌演练、AI云诊断、主动预警、架构健康度、云运维问答、云资源查询、云成本优化、安全合规、云资源盘点、闲置资源检查、云产品最佳实践等AIOps、ChatOps、CloudOps操作时使用。",
|
|
625
|
+
whenToUse: "用户要求进入 CloudQ 模式、使用 CloudQ、咨询云上架构/资源/成本/巡检/诊断等多云或腾讯云运维问题,或点击输入栏 CloudQ 按钮时使用;也适用于架构图查看/评估、AI 巡检、容量监测、混沌演练、云诊断等场景。",
|
|
626
|
+
source: "bundled",
|
|
627
|
+
resourceBase: {
|
|
628
|
+
kind: "directory",
|
|
629
|
+
path: skillDirectory()
|
|
630
|
+
},
|
|
631
|
+
content: renderedSkillContent(),
|
|
632
|
+
invocation: {
|
|
633
|
+
modelInvocable: true,
|
|
634
|
+
userInvocable: true
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
}, "dsh-cloudq: CloudQ skill");
|
|
636
638
|
ctx.effect(() => {
|
|
637
639
|
const disposers = [];
|
|
638
640
|
disposers.push(ctx.webServer.register({
|
|
@@ -650,41 +652,6 @@ function apply(ctx) {
|
|
|
650
652
|
}
|
|
651
653
|
}
|
|
652
654
|
}));
|
|
653
|
-
disposers.push(ctx.webServer.register({
|
|
654
|
-
kind: "exact",
|
|
655
|
-
path: "/api/dsh-cloudq/login/url",
|
|
656
|
-
handler: async (request, response) => {
|
|
657
|
-
try {
|
|
658
|
-
assertSafeRequest(request, "POST");
|
|
659
|
-
const result = await authorizeUrl();
|
|
660
|
-
sendJson(response, 200, {
|
|
661
|
-
ok: true,
|
|
662
|
-
authorize_url: result.authorize_url,
|
|
663
|
-
state: result.state
|
|
664
|
-
});
|
|
665
|
-
} catch (error) {
|
|
666
|
-
sendError(response, error);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}));
|
|
670
|
-
disposers.push(ctx.webServer.register({
|
|
671
|
-
kind: "exact",
|
|
672
|
-
path: "/api/dsh-cloudq/login/save",
|
|
673
|
-
handler: async (request, response) => {
|
|
674
|
-
try {
|
|
675
|
-
assertSafeRequest(request, "POST");
|
|
676
|
-
const body = await readJsonBody(request);
|
|
677
|
-
const code = typeof body?.code === "string" ? body.code.trim() : "";
|
|
678
|
-
if (!code) throw new HttpError(400, "missing-code", "缺少授权码。");
|
|
679
|
-
sendJson(response, 200, {
|
|
680
|
-
ok: true,
|
|
681
|
-
status: await saveAuthCode(code)
|
|
682
|
-
});
|
|
683
|
-
} catch (error) {
|
|
684
|
-
sendError(response, error);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}));
|
|
688
655
|
disposers.push(ctx.webServer.register({
|
|
689
656
|
kind: "exact",
|
|
690
657
|
path: "/api/dsh-cloudq/logout",
|
package/package.json
CHANGED