openyida 2026.7.13 → 2026.7.14-2
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 +15 -22
- package/bin/yida.js +72 -220
- package/lib/agent-center/api.js +2 -2
- package/lib/aggregate-table/aggregate-table.js +2 -2
- package/lib/ai/ai.js +7 -12
- package/lib/app/canvas-compile.js +2 -2
- package/lib/app/create-app.js +5 -19
- package/lib/app/create-form.js +54 -76
- package/lib/app/create-page.js +4 -19
- package/lib/app/er.js +11 -8
- package/lib/app/export-app.js +2 -2
- package/lib/app/externalize-form.js +12 -10
- package/lib/app/get-schema.js +12 -10
- package/lib/app/import-app.js +6 -22
- package/lib/app/list-forms.js +3 -19
- package/lib/app/nav-group.js +6 -19
- package/lib/app/publish.js +60 -198
- package/lib/app/update-app.js +4 -18
- package/lib/app/update-form-config.js +20 -113
- package/lib/app-permission/app-permission.js +2 -2
- package/lib/auth/oauth-loopback.js +156 -0
- package/lib/auth/org.js +169 -322
- package/lib/auth/token-auth.js +346 -0
- package/lib/auth/token-store.js +174 -0
- package/lib/basic-info/basic-info.js +11 -12
- package/lib/bridge/bridge.js +29 -27
- package/lib/connector/api.js +4 -4
- package/lib/core/agent-capabilities.js +92 -8
- package/lib/core/batch.js +8 -8
- package/lib/core/check-data.js +2 -2
- package/lib/core/command-manifest.js +3 -3
- package/lib/core/doctor.js +19 -22
- package/lib/core/env-cmd.js +1 -3
- package/lib/core/env-manager.js +8 -121
- package/lib/core/env.js +30 -72
- package/lib/core/locales/ar.js +5 -5
- package/lib/core/locales/de.js +5 -5
- package/lib/core/locales/en.js +26 -26
- package/lib/core/locales/es.js +5 -5
- package/lib/core/locales/fr.js +5 -5
- package/lib/core/locales/hi.js +5 -5
- package/lib/core/locales/ja.js +14 -14
- package/lib/core/locales/ko.js +5 -5
- package/lib/core/locales/pt.js +5 -5
- package/lib/core/locales/vi.js +5 -5
- package/lib/core/locales/zh-HK.js +15 -15
- package/lib/core/locales/zh.js +26 -26
- package/lib/core/query-data.js +2 -2
- package/lib/core/task-center.js +2 -2
- package/lib/core/utils.js +156 -400
- package/lib/core/yida-client.js +57 -22
- package/lib/corp-efficiency/corp-efficiency.js +3 -3
- package/lib/corp-manager/api.js +2 -2
- package/lib/db/db-seq-fix.js +20 -25
- package/lib/flash-note/flash-to-prd.js +2 -2
- package/lib/i18n-management/i18n-management.js +2 -2
- package/lib/integration/integration-check.js +10 -7
- package/lib/integration/integration-create.js +11 -8
- package/lib/integration/integration-list.js +11 -8
- package/lib/mcp/server.js +5 -54
- package/lib/page-config/get-page-config.js +2 -2
- package/lib/page-config/save-share-config.js +2 -2
- package/lib/page-config/verify-short-url.js +2 -2
- package/lib/permission/get-permission.js +2 -2
- package/lib/permission/save-permission.js +2 -2
- package/lib/process/ai-form-setting.js +2 -2
- package/lib/process/create-process.js +2 -2
- package/lib/process/preview-process.js +2 -2
- package/lib/report/append.js +3 -3
- package/lib/report/index.js +3 -3
- package/package.json +1 -1
- package/scripts/check-syntax.js +6 -0
- package/scripts/e2e-real/full-runner.js +2 -10
- package/scripts/e2e-real/runner.js +0 -31
- package/scripts/eval/screenshot.js +27 -69
- package/scripts/nightly-smoke.js +16 -34
- package/scripts/postinstall.js +6 -2
- package/yida-skills/SKILL.md +10 -6
- package/yida-skills/references/development-rules.md +2 -2
- package/yida-skills/references/setup-and-env.md +10 -9
- package/yida-skills/skills/sls-log-workbench/SKILL.md +2 -2
- package/yida-skills/skills/sls-log-workbench/sls-query.js +27 -54
- package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +1 -1
- package/yida-skills/skills/yida-integration/SKILL.md +3 -3
- package/yida-skills/skills/yida-login/SKILL.md +56 -74
- package/yida-skills/skills/yida-logout/SKILL.md +13 -12
- package/yida-skills/skills/yida-process-rule/SKILL.md +1 -1
- package/yida-skills/skills/yida-publish-page/SKILL.md +1 -1
- package/yida-skills/skills/yida-report/references/report-api-guide.md +4 -20
- package/yida-skills/skills-index.json +4 -4
- package/lib/auth/auth.js +0 -313
- package/lib/auth/cdp-browser-login.js +0 -390
- package/lib/auth/codex-login.js +0 -71
- package/lib/auth/login.js +0 -550
- package/lib/auth/qr-login.js +0 -1575
package/lib/auth/org.js
CHANGED
|
@@ -1,363 +1,210 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* org.js - 组织管理模块
|
|
3
|
-
*
|
|
4
|
-
* 提供组织切换能力,支持:
|
|
5
|
-
* - 列出用户可访问的组织
|
|
6
|
-
* - 切换组织(无需重新登录)
|
|
7
|
-
* - 交互式组织选择
|
|
8
|
-
*
|
|
9
|
-
* 切换组织原理:
|
|
10
|
-
* 通过一系列 HTTP 请求完成组织切换,无需重新登录。
|
|
11
|
-
* 流程:
|
|
12
|
-
* 1. GET /start.html?corpid={corpId}&switchCorp=true
|
|
13
|
-
* 2. GET /start.html?corpid={corpId}&
|
|
14
|
-
* 3. 跟随重定向获取新 Cookie
|
|
15
|
-
*
|
|
16
|
-
* 导出函数:
|
|
17
|
-
* listOrganizations() - 列出可访问的组织
|
|
18
|
-
* switchOrganization() - 切换到指定组织
|
|
19
|
-
* interactiveSwitch() - 交互式组织选择
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
1
|
'use strict';
|
|
23
2
|
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const {
|
|
27
|
-
const { saveCookieCache } = require('./login');
|
|
28
|
-
const { saveAuthConfig, loadAuthConfig } = require('./auth');
|
|
29
|
-
const { t } = require('../core/i18n');
|
|
30
|
-
|
|
31
|
-
// ── HTTP 请求工具 ─────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 发送 HTTP GET 请求并跟随重定向,提取响应中的 Cookie
|
|
35
|
-
* @param {string} url - 完整 URL
|
|
36
|
-
* @param {Array} cookies - 当前 Cookie 列表
|
|
37
|
-
* @param {boolean} _followRedirect - 是否跟随重定向(保留参数以保持 API 一致性)
|
|
38
|
-
* @returns {Promise<{statusCode: number, headers: object, cookies: Array}>}
|
|
39
|
-
*/
|
|
40
|
-
function httpGetWithCookies(url, cookies, _followRedirect = true) {
|
|
41
|
-
return new Promise((resolve, reject) => {
|
|
42
|
-
const cookieHeader = cookies.map((c) => `${c.name}=${c.value}`).join('; ');
|
|
43
|
-
const parsedUrl = new URL(url);
|
|
44
|
-
const isHttps = parsedUrl.protocol === 'https:';
|
|
45
|
-
const requestModule = isHttps ? https : http;
|
|
46
|
-
|
|
47
|
-
const options = {
|
|
48
|
-
hostname: parsedUrl.hostname,
|
|
49
|
-
port: parsedUrl.port || (isHttps ? 443 : 80),
|
|
50
|
-
path: parsedUrl.pathname + parsedUrl.search,
|
|
51
|
-
method: 'GET',
|
|
52
|
-
headers: {
|
|
53
|
-
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
54
|
-
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
55
|
-
'Cookie': cookieHeader,
|
|
56
|
-
},
|
|
57
|
-
timeout: 30000,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// 不自动跟随重定向,手动处理以提取 Cookie
|
|
61
|
-
const req = requestModule.request(options, (res) => {
|
|
62
|
-
let data = '';
|
|
63
|
-
res.on('data', (chunk) => { data += chunk; });
|
|
64
|
-
res.on('end', () => {
|
|
65
|
-
// 提取 Set-Cookie 中的新 Cookie
|
|
66
|
-
const setCookies = res.headers['set-cookie'] || [];
|
|
67
|
-
const newCookies = parseSetCookies(setCookies, cookies);
|
|
3
|
+
const { createAuthRef, createYidaClient } = require('../core/yida-client');
|
|
4
|
+
const { loadTokenSession, clearTokenSession } = require('./token-store');
|
|
5
|
+
const { tokenLogin, tokenLogout } = require('./token-auth');
|
|
68
6
|
|
|
69
|
-
|
|
70
|
-
statusCode: res.statusCode,
|
|
71
|
-
headers: res.headers,
|
|
72
|
-
cookies: newCookies,
|
|
73
|
-
location: res.headers.location,
|
|
74
|
-
body: data,
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
7
|
+
const LIST_CORP_INFOS_PATH = '/query/userservice/listCorpInfos.json';
|
|
78
8
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
9
|
+
function getArgValue(args, name) {
|
|
10
|
+
const index = args.indexOf(name);
|
|
11
|
+
if (index === -1 || !args[index + 1] || args[index + 1].startsWith('--')) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return args[index + 1];
|
|
83
15
|
}
|
|
84
16
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* @param {Array} existingCookies - 现有 Cookie 列表
|
|
89
|
-
* @returns {Array} 合并后的 Cookie 列表
|
|
90
|
-
*/
|
|
91
|
-
function parseSetCookies(setCookies, existingCookies) {
|
|
92
|
-
const cookieMap = new Map();
|
|
93
|
-
|
|
94
|
-
// 先添加现有 Cookie
|
|
95
|
-
for (const cookie of existingCookies) {
|
|
96
|
-
cookieMap.set(cookie.name, cookie);
|
|
97
|
-
}
|
|
17
|
+
function hasFlag(args, name) {
|
|
18
|
+
return args.includes(name);
|
|
19
|
+
}
|
|
98
20
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (parts.length >= 2) {
|
|
103
|
-
const name = parts[0].trim();
|
|
104
|
-
const value = parts.slice(1).join('=').trim();
|
|
105
|
-
cookieMap.set(name, { name, value });
|
|
106
|
-
}
|
|
21
|
+
function getPayload(response) {
|
|
22
|
+
if (!response || typeof response !== 'object') {
|
|
23
|
+
return response;
|
|
107
24
|
}
|
|
108
|
-
|
|
109
|
-
return Array.from(cookieMap.values());
|
|
25
|
+
return response.content || response.data || response.result || response;
|
|
110
26
|
}
|
|
111
27
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
28
|
+
function normalizeCorpList(response) {
|
|
29
|
+
const payload = getPayload(response);
|
|
30
|
+
const list = Array.isArray(payload)
|
|
31
|
+
? payload
|
|
32
|
+
: Array.isArray(payload && payload.list)
|
|
33
|
+
? payload.list
|
|
34
|
+
: Array.isArray(payload && payload.corpInfos)
|
|
35
|
+
? payload.corpInfos
|
|
36
|
+
: [];
|
|
37
|
+
|
|
38
|
+
return list
|
|
39
|
+
.map((corp) => ({
|
|
40
|
+
corpId: corp.corpId || corp.corp_id || corp.id,
|
|
41
|
+
corpName: corp.corpName || corp.corp_name || corp.name || corp.corpId || corp.id,
|
|
42
|
+
logo: corp.logo,
|
|
43
|
+
namespace: corp.namespace || '',
|
|
44
|
+
}))
|
|
45
|
+
.filter((corp) => corp.corpId);
|
|
46
|
+
}
|
|
128
47
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
48
|
+
async function listOrganizations(options = {}) {
|
|
49
|
+
const authRef = createAuthRef();
|
|
50
|
+
const response = await createYidaClient({ authRef }).get(LIST_CORP_INFOS_PATH);
|
|
51
|
+
if (response && response.success === false) {
|
|
52
|
+
throw new Error(response.errorMsg || response.message || response.errorCode || 'list corp infos failed');
|
|
133
53
|
}
|
|
54
|
+
const organizations = normalizeCorpList(response);
|
|
55
|
+
return {
|
|
56
|
+
ok: true,
|
|
57
|
+
auth_mode: 'token',
|
|
58
|
+
status: 'ok',
|
|
59
|
+
current_corp_id: authRef.corpId,
|
|
60
|
+
count: organizations.length,
|
|
61
|
+
organizations: organizations.map((corp) => ({
|
|
62
|
+
...corp,
|
|
63
|
+
isCurrent: !!authRef.corpId && corp.corpId === authRef.corpId,
|
|
64
|
+
})),
|
|
65
|
+
raw: options.includeRaw ? response : undefined,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
134
68
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const recentCorps = authConfig?.recentCorps || [];
|
|
139
|
-
|
|
140
|
-
// 构建组织列表
|
|
141
|
-
const organizations = [];
|
|
142
|
-
|
|
143
|
-
// 添加当前组织
|
|
144
|
-
organizations.push({
|
|
145
|
-
corpId,
|
|
146
|
-
name: t('org.current_org'),
|
|
147
|
-
isCurrent: true,
|
|
148
|
-
lastUsed: new Date().toISOString(),
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// 添加历史组织
|
|
152
|
-
for (const org of recentCorps) {
|
|
153
|
-
if (org.corpId !== corpId) {
|
|
154
|
-
organizations.push({
|
|
155
|
-
corpId: org.corpId,
|
|
156
|
-
name: org.name || org.corpId,
|
|
157
|
-
isCurrent: false,
|
|
158
|
-
lastUsed: org.lastUsed,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
69
|
+
async function switchOrganization(targetCorpId, options = {}) {
|
|
70
|
+
if (!targetCorpId) {
|
|
71
|
+
throw new Error('corpId is required. Usage: openyida org switch --corp-id dingXXX');
|
|
161
72
|
}
|
|
162
73
|
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
74
|
+
const currentSession = loadTokenSession(options);
|
|
75
|
+
if (currentSession && currentSession.corp_id === targetCorpId) {
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
auth_mode: 'token',
|
|
79
|
+
status: 'already_in_org',
|
|
80
|
+
can_auto_use: true,
|
|
81
|
+
corp_id: currentSession.corp_id,
|
|
82
|
+
user_id: currentSession.user_id,
|
|
83
|
+
user_name: currentSession.user_name,
|
|
84
|
+
base_url: currentSession.base_url,
|
|
85
|
+
message: 'already in target organization',
|
|
86
|
+
};
|
|
173
87
|
}
|
|
174
88
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* 切换到指定组织(无需重新登录)
|
|
183
|
-
* @param {string} targetCorpId - 目标组织 ID
|
|
184
|
-
* @param {object} cookieData - 当前 Cookie 数据
|
|
185
|
-
* @returns {Promise<object>} 切换结果
|
|
186
|
-
*/
|
|
187
|
-
async function switchOrganization(targetCorpId, cookieData) {
|
|
188
|
-
const { c, banner, label, info, success: chalkSuccess, warn: chalkWarn, fail: chalkFail, step, sep } = require('../core/chalk');
|
|
189
|
-
|
|
190
|
-
banner(t('org.switch_title'), { stderr: false });
|
|
191
|
-
|
|
192
|
-
const cookies = cookieData.cookies;
|
|
193
|
-
const { corpId: currentCorpId } = extractInfoFromCookies(cookies);
|
|
89
|
+
const loginOptions = {
|
|
90
|
+
...options,
|
|
91
|
+
endpoint: options.endpoint || (currentSession && currentSession.base_url),
|
|
92
|
+
clientId: options.clientId || (currentSession && currentSession.client_id),
|
|
93
|
+
};
|
|
194
94
|
|
|
195
|
-
|
|
196
|
-
|
|
95
|
+
if (currentSession) {
|
|
96
|
+
await tokenLogout(options);
|
|
97
|
+
} else {
|
|
98
|
+
clearTokenSession(options);
|
|
99
|
+
}
|
|
197
100
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
101
|
+
const loginResult = await tokenLogin(loginOptions);
|
|
102
|
+
if (!loginResult || !loginResult.access_token) {
|
|
103
|
+
clearTokenSession(options);
|
|
201
104
|
return {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
105
|
+
...(loginResult || {}),
|
|
106
|
+
ok: false,
|
|
107
|
+
auth_mode: 'token',
|
|
108
|
+
status: 'token_not_issued',
|
|
109
|
+
can_auto_use: false,
|
|
110
|
+
message: (loginResult && loginResult.message) || 'login did not issue access_token',
|
|
205
111
|
};
|
|
206
112
|
}
|
|
207
113
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Step 2: 确认切换
|
|
217
|
-
step(2, t('org.step2'), false);
|
|
218
|
-
const step2Url = `${baseUrl}/start.html?corpid=${targetCorpId}&`;
|
|
219
|
-
const step2Result = await httpGetWithCookies(step2Url, step1Result.cookies, false);
|
|
220
|
-
|
|
221
|
-
// Step 3-4: 获取新 Cookie(跟随重定向)
|
|
222
|
-
step(3, t('org.step3'), false);
|
|
223
|
-
const step3Url = `${baseUrl}/start.html?corpid=${targetCorpId}&`;
|
|
224
|
-
const step3Result = await httpGetWithCookies(step3Url, step2Result.cookies, false);
|
|
225
|
-
|
|
226
|
-
// 处理重定向
|
|
227
|
-
let finalCookies = step3Result.cookies;
|
|
228
|
-
let currentUrl = step3Result.location;
|
|
229
|
-
|
|
230
|
-
// 跟随重定向最多 5 次
|
|
231
|
-
let redirectCount = 0;
|
|
232
|
-
while (currentUrl && redirectCount < 5) {
|
|
233
|
-
redirectCount++;
|
|
234
|
-
info(`${t('org.redirect', redirectCount)}`, false);
|
|
235
|
-
|
|
236
|
-
// 构建完整 URL
|
|
237
|
-
if (!currentUrl.startsWith('http')) {
|
|
238
|
-
currentUrl = new URL(currentUrl, baseUrl).toString();
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const redirectResult = await httpGetWithCookies(currentUrl, finalCookies, false);
|
|
242
|
-
finalCookies = redirectResult.cookies;
|
|
243
|
-
currentUrl = redirectResult.location;
|
|
244
|
-
|
|
245
|
-
// 如果到达工作台,停止
|
|
246
|
-
if (currentUrl && currentUrl.includes('workPlatform')) {
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// 提取新的 csrf_token 和 corpId
|
|
252
|
-
const { csrfToken, corpId: newCorpId, userId } = extractInfoFromCookies(finalCookies);
|
|
253
|
-
|
|
254
|
-
if (!csrfToken) {
|
|
255
|
-
chalkFail(t('org.switch_failed_no_csrf'), { exit: false });
|
|
256
|
-
console.log(` ${sep()}\n`);
|
|
257
|
-
return {
|
|
258
|
-
success: false,
|
|
259
|
-
message: 'No csrf_token in new cookies',
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// 保存新的 Cookie
|
|
264
|
-
const newBaseUrl = baseUrl;
|
|
265
|
-
saveCookieCache(finalCookies, newBaseUrl);
|
|
266
|
-
|
|
267
|
-
// 更新 auth 配置
|
|
268
|
-
const authConfig = loadAuthConfig() || {};
|
|
269
|
-
authConfig.corpId = newCorpId;
|
|
270
|
-
authConfig.userId = userId;
|
|
271
|
-
authConfig.switchTime = new Date().toISOString();
|
|
272
|
-
|
|
273
|
-
// 更新历史组织列表
|
|
274
|
-
if (!authConfig.recentCorps) {
|
|
275
|
-
authConfig.recentCorps = [];
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// 移除旧记录,添加新记录
|
|
279
|
-
authConfig.recentCorps = authConfig.recentCorps.filter((c) => c.corpId !== newCorpId);
|
|
280
|
-
authConfig.recentCorps.unshift({
|
|
281
|
-
corpId: newCorpId,
|
|
282
|
-
name: t('org.switched_org'),
|
|
283
|
-
lastUsed: new Date().toISOString(),
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// 保留最近 10 个组织
|
|
287
|
-
authConfig.recentCorps = authConfig.recentCorps.slice(0, 10);
|
|
288
|
-
saveAuthConfig(authConfig);
|
|
114
|
+
if (loginResult.corp_id !== targetCorpId) {
|
|
115
|
+
await tokenLogout(options);
|
|
116
|
+
const error = new Error(`登录到的组织与目标组织不一致:target=${targetCorpId}, actual=${loginResult.corp_id || 'unknown'}`);
|
|
117
|
+
error.code = 'ORG_SWITCH_CORP_MISMATCH';
|
|
118
|
+
error.targetCorpId = targetCorpId;
|
|
119
|
+
error.actualCorpId = loginResult.corp_id;
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
289
122
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
123
|
+
return {
|
|
124
|
+
ok: true,
|
|
125
|
+
auth_mode: 'token',
|
|
126
|
+
status: 'switched',
|
|
127
|
+
can_auto_use: true,
|
|
128
|
+
previous_corp_id: currentSession && currentSession.corp_id,
|
|
129
|
+
corp_id: loginResult.corp_id,
|
|
130
|
+
user_id: loginResult.user_id,
|
|
131
|
+
user_name: loginResult.user_name,
|
|
132
|
+
base_url: loginResult.base_url,
|
|
133
|
+
message: 'switched organization by OAuth re-login',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
294
136
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
baseUrl: newBaseUrl,
|
|
301
|
-
cookies: finalCookies,
|
|
302
|
-
};
|
|
303
|
-
} catch (error) {
|
|
304
|
-
chalkFail(t('org.switch_error', error.message), { exit: false });
|
|
137
|
+
function printList(result) {
|
|
138
|
+
const { c, banner, sep } = require('../core/chalk');
|
|
139
|
+
banner('openyida org list - 组织列表', { stderr: false });
|
|
140
|
+
if (!result.organizations.length) {
|
|
141
|
+
console.log(' 暂无可访问组织');
|
|
305
142
|
console.log(` ${sep()}\n`);
|
|
306
|
-
return
|
|
307
|
-
success: false,
|
|
308
|
-
message: error.message,
|
|
309
|
-
};
|
|
143
|
+
return;
|
|
310
144
|
}
|
|
145
|
+
result.organizations.forEach((corp) => {
|
|
146
|
+
const icon = corp.isCurrent ? `${c.green}✔${c.reset}` : `${c.dim}○${c.reset}`;
|
|
147
|
+
const current = corp.isCurrent ? ` ${c.green}(当前)${c.reset}` : '';
|
|
148
|
+
console.log(` ${icon} ${corp.corpName}${current}`);
|
|
149
|
+
console.log(` ${c.dim}corpId: ${corp.corpId}${c.reset}`);
|
|
150
|
+
});
|
|
151
|
+
console.log(`\n ${sep()}\n`);
|
|
311
152
|
}
|
|
312
153
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
};
|
|
154
|
+
function printSwitch(result) {
|
|
155
|
+
const { banner, label, success, warn, sep } = require('../core/chalk');
|
|
156
|
+
banner('openyida org switch - 组织切换', { stderr: false });
|
|
157
|
+
if (result.status === 'already_in_org') {
|
|
158
|
+
warn('已在目标组织中,无需切换', false);
|
|
159
|
+
} else {
|
|
160
|
+
success('组织切换成功', false);
|
|
161
|
+
}
|
|
162
|
+
if (result.previous_corp_id) {
|
|
163
|
+
label('From', result.previous_corp_id, { stderr: false });
|
|
164
|
+
}
|
|
165
|
+
label('Corp ID', result.corp_id || '', { stderr: false });
|
|
166
|
+
if (result.user_id) {
|
|
167
|
+
label('User ID', result.user_id, { stderr: false });
|
|
328
168
|
}
|
|
169
|
+
console.log(` ${sep()}\n`);
|
|
170
|
+
}
|
|
329
171
|
|
|
330
|
-
|
|
331
|
-
const
|
|
172
|
+
async function run(args = []) {
|
|
173
|
+
const subCommand = args[0];
|
|
174
|
+
const json = hasFlag(args, '--json');
|
|
175
|
+
const options = {
|
|
176
|
+
quiet: hasFlag(args, '--quiet') || json,
|
|
177
|
+
clientId: getArgValue(args, '--client-id'),
|
|
178
|
+
};
|
|
332
179
|
|
|
333
|
-
if (
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
180
|
+
if (subCommand === 'list') {
|
|
181
|
+
const result = await listOrganizations(options);
|
|
182
|
+
if (json) {
|
|
183
|
+
console.log(JSON.stringify(result, null, 2));
|
|
184
|
+
} else {
|
|
185
|
+
printList(result);
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
340
188
|
}
|
|
341
189
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
190
|
+
if (subCommand === 'switch') {
|
|
191
|
+
const targetCorpId = getArgValue(args, '--corp-id') || args.slice(1).find(arg => !arg.startsWith('--'));
|
|
192
|
+
const result = await switchOrganization(targetCorpId, options);
|
|
193
|
+
if (json) {
|
|
194
|
+
console.log(JSON.stringify(result, null, 2));
|
|
195
|
+
} else {
|
|
196
|
+
printSwitch(result);
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
351
200
|
|
|
352
|
-
|
|
353
|
-
success: false,
|
|
354
|
-
message: 'Interactive mode not supported, please use --corp-id option',
|
|
355
|
-
organizations: switchableOrgs,
|
|
356
|
-
};
|
|
201
|
+
throw new Error('Usage: openyida org <list|switch>');
|
|
357
202
|
}
|
|
358
203
|
|
|
359
204
|
module.exports = {
|
|
205
|
+
LIST_CORP_INFOS_PATH,
|
|
360
206
|
listOrganizations,
|
|
207
|
+
normalizeCorpList,
|
|
208
|
+
run,
|
|
361
209
|
switchOrganization,
|
|
362
|
-
interactiveSwitch,
|
|
363
210
|
};
|