@cloudbase/manager-node 4.11.0-alpha.6 → 4.11.0-alpha.8
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/lib/agent/index.js +607 -16
- package/lib/agent/type.js +1 -0
- package/lib/environment.js +10 -0
- package/lib/function/index.js +84 -25
- package/lib/index.js +6 -0
- package/lib/log/index.js +105 -0
- package/lib/log/types.js +24 -0
- package/lib/permission/index.js +313 -0
- package/lib/permission/types.js +2 -0
- package/package.json +1 -1
- package/types/agent/index.d.ts +115 -5
- package/types/agent/type.d.ts +389 -0
- package/types/environment.d.ts +6 -0
- package/types/function/index.d.ts +30 -1
- package/types/index.d.ts +4 -0
- package/types/log/index.d.ts +53 -0
- package/types/log/types.d.ts +177 -0
- package/types/permission/index.d.ts +31 -0
- package/types/permission/types.d.ts +127 -0
package/lib/environment.js
CHANGED
|
@@ -8,6 +8,7 @@ const agent_1 = require("./agent");
|
|
|
8
8
|
const storage_1 = require("./storage");
|
|
9
9
|
const env_1 = require("./env");
|
|
10
10
|
const common_1 = require("./common");
|
|
11
|
+
const log_1 = require("./log");
|
|
11
12
|
const error_1 = require("./error");
|
|
12
13
|
const constant_1 = require("./constant");
|
|
13
14
|
const utils_1 = require("./utils");
|
|
@@ -17,6 +18,7 @@ const access_1 = require("./access");
|
|
|
17
18
|
const user_1 = require("./user");
|
|
18
19
|
const cloudBaseRun_1 = require("./cloudBaseRun");
|
|
19
20
|
const mysql_1 = require("./mysql");
|
|
21
|
+
const permission_1 = require("./permission");
|
|
20
22
|
class Environment {
|
|
21
23
|
constructor(context, envId) {
|
|
22
24
|
this.inited = false;
|
|
@@ -31,12 +33,14 @@ class Environment {
|
|
|
31
33
|
this.databaseService = new database_1.DatabaseService(this);
|
|
32
34
|
this.storageService = new storage_1.StorageService(this);
|
|
33
35
|
this.envService = new env_1.EnvService(this);
|
|
36
|
+
this.logService = new log_1.LogService(this);
|
|
34
37
|
this.hostingService = new hosting_1.HostingService(this);
|
|
35
38
|
this.thirdService = new third_1.ThirdService(this);
|
|
36
39
|
this.accessService = new access_1.AccessService(this);
|
|
37
40
|
this.userService = new user_1.UserService(this);
|
|
38
41
|
this.cloudBaseRunService = new cloudBaseRun_1.CloudBaseRunService(this);
|
|
39
42
|
this.mysqlService = new mysql_1.MysqlService(this);
|
|
43
|
+
this.permissionService = new permission_1.PermissionService(this);
|
|
40
44
|
}
|
|
41
45
|
async lazyInit() {
|
|
42
46
|
if (!this.inited) {
|
|
@@ -78,6 +82,9 @@ class Environment {
|
|
|
78
82
|
getEnvService() {
|
|
79
83
|
return this.envService;
|
|
80
84
|
}
|
|
85
|
+
getLogService() {
|
|
86
|
+
return this.logService;
|
|
87
|
+
}
|
|
81
88
|
getHostingService() {
|
|
82
89
|
return this.hostingService;
|
|
83
90
|
}
|
|
@@ -96,6 +103,9 @@ class Environment {
|
|
|
96
103
|
getMysqlService() {
|
|
97
104
|
return this.mysqlService;
|
|
98
105
|
}
|
|
106
|
+
getPermissionService() {
|
|
107
|
+
return this.permissionService;
|
|
108
|
+
}
|
|
99
109
|
getCommonService(serviceType = 'tcb', serviceVersion) {
|
|
100
110
|
return new common_1.CommonService(this, serviceType, serviceVersion);
|
|
101
111
|
}
|
package/lib/function/index.js
CHANGED
|
@@ -924,6 +924,56 @@ class FunctionService {
|
|
|
924
924
|
});
|
|
925
925
|
}
|
|
926
926
|
}
|
|
927
|
+
/**
|
|
928
|
+
* 更新函数代码和配置(带进度信息)
|
|
929
|
+
* 支持同时更新代码和配置,按顺序执行:等待就绪 → 更新代码 → 等待就绪 → 更新配置 → 等待就绪
|
|
930
|
+
* @param options 更新选项
|
|
931
|
+
* @returns 更新结果,包含耗时信息
|
|
932
|
+
*/
|
|
933
|
+
async updateFunctionWithProgress(options) {
|
|
934
|
+
const { name, code, config } = options;
|
|
935
|
+
const startTime = Date.now();
|
|
936
|
+
const details = [];
|
|
937
|
+
// codeSecret 在不同阶段可能不同:
|
|
938
|
+
// - 更新代码前/后:用旧的 codeSecret(函数此时还是旧密钥)
|
|
939
|
+
// - 更新配置后:如果 config 中带了新 codeSecret,函数密钥已变更,需用新值
|
|
940
|
+
const oldCodeSecret = (code === null || code === void 0 ? void 0 : code.codeSecret) || (config === null || config === void 0 ? void 0 : config.codeSecret);
|
|
941
|
+
const newCodeSecret = (config === null || config === void 0 ? void 0 : config.codeSecret) || (code === null || code === void 0 ? void 0 : code.codeSecret);
|
|
942
|
+
// 1. 等待函数状态就绪(此时函数还是旧密钥)
|
|
943
|
+
details.push('等待函数状态就绪...');
|
|
944
|
+
await this.waitFunctionActive(name, oldCodeSecret);
|
|
945
|
+
details.push(`函数状态就绪 (${Math.round((Date.now() - startTime) / 1000)}s)`);
|
|
946
|
+
// 2. 更新代码
|
|
947
|
+
if (code && (code.functionPath || code.base64Code)) {
|
|
948
|
+
details.push('开始更新代码...');
|
|
949
|
+
await this.updateFunctionCode(Object.assign({ func: {
|
|
950
|
+
name,
|
|
951
|
+
// 从 config 取公共字段
|
|
952
|
+
runtime: config === null || config === void 0 ? void 0 : config.runtime,
|
|
953
|
+
installDependency: config === null || config === void 0 ? void 0 : config.installDependency,
|
|
954
|
+
ignore: config === null || config === void 0 ? void 0 : config.ignore,
|
|
955
|
+
codeSecret: oldCodeSecret
|
|
956
|
+
} }, code));
|
|
957
|
+
details.push(`代码更新完成 (${Math.round((Date.now() - startTime) / 1000)}s)`);
|
|
958
|
+
// 等待函数再次就绪(代码更新不改变 codeSecret,仍用旧值)
|
|
959
|
+
await this.waitFunctionActive(name, oldCodeSecret);
|
|
960
|
+
}
|
|
961
|
+
// 3. 更新配置
|
|
962
|
+
if (config) {
|
|
963
|
+
details.push('开始更新配置...');
|
|
964
|
+
await this.updateFunctionConfig(Object.assign({ name }, config));
|
|
965
|
+
details.push(`配置更新完成 (${Math.round((Date.now() - startTime) / 1000)}s)`);
|
|
966
|
+
// 等待函数再次就绪(配置更新后 codeSecret 可能已变更,用新值)
|
|
967
|
+
await this.waitFunctionActive(name, newCodeSecret);
|
|
968
|
+
}
|
|
969
|
+
const elapsedTime = Date.now() - startTime;
|
|
970
|
+
details.push(`全部更新完成 (${Math.round(elapsedTime / 1000)}s)`);
|
|
971
|
+
return {
|
|
972
|
+
elapsedTime,
|
|
973
|
+
message: `更新成功,总耗时 ${Math.round(elapsedTime / 1000)}s`,
|
|
974
|
+
details
|
|
975
|
+
};
|
|
976
|
+
}
|
|
927
977
|
/**
|
|
928
978
|
* 调用云函数
|
|
929
979
|
* @param {string} name 云函数名称
|
|
@@ -1471,7 +1521,13 @@ class FunctionService {
|
|
|
1471
1521
|
}
|
|
1472
1522
|
});
|
|
1473
1523
|
return new Promise((resolve, reject) => {
|
|
1524
|
+
// 添加超时保护
|
|
1525
|
+
const timeout = setTimeout(() => {
|
|
1526
|
+
packer.clean();
|
|
1527
|
+
reject(new error_1.CloudBaseError(`[${func.name}] COS 上传超时(60秒)`));
|
|
1528
|
+
}, 60000);
|
|
1474
1529
|
cos.sliceUploadFile(uploadParams, async (err, data) => {
|
|
1530
|
+
clearTimeout(timeout);
|
|
1475
1531
|
// 清理临时文件
|
|
1476
1532
|
await packer.clean();
|
|
1477
1533
|
if (err) {
|
|
@@ -1550,29 +1606,6 @@ class FunctionService {
|
|
|
1550
1606
|
UnixTimestamp
|
|
1551
1607
|
};
|
|
1552
1608
|
}
|
|
1553
|
-
async createAccessPath(name, path) {
|
|
1554
|
-
const access = this.environment.getAccessService();
|
|
1555
|
-
try {
|
|
1556
|
-
await access.createAccess({
|
|
1557
|
-
name,
|
|
1558
|
-
path
|
|
1559
|
-
});
|
|
1560
|
-
}
|
|
1561
|
-
catch (e) {
|
|
1562
|
-
// 当 Path 存在时,校验 Path 绑定的函数是不是当前函数
|
|
1563
|
-
if (e.code === 'InvalidParameter.APICreated') {
|
|
1564
|
-
const { APISet } = await access.getAccessList({
|
|
1565
|
-
name
|
|
1566
|
-
});
|
|
1567
|
-
if ((APISet === null || APISet === void 0 ? void 0 : APISet[0].Name) !== name || (APISet === null || APISet === void 0 ? void 0 : APISet[0].Type) !== 1) {
|
|
1568
|
-
throw e;
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
else {
|
|
1572
|
-
throw e;
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
1609
|
async getCodeParams(options, installDependency) {
|
|
1577
1610
|
const { func, functionPath, functionRootPath, base64Code, deployMode } = options;
|
|
1578
1611
|
// 直接传入 base64Code 的情况,校验大小
|
|
@@ -1625,6 +1658,29 @@ class FunctionService {
|
|
|
1625
1658
|
TempCosObjectName: `/${legacyResult.Key}`
|
|
1626
1659
|
};
|
|
1627
1660
|
}
|
|
1661
|
+
async createAccessPath(name, path) {
|
|
1662
|
+
const access = this.environment.getAccessService();
|
|
1663
|
+
try {
|
|
1664
|
+
await access.createAccess({
|
|
1665
|
+
name,
|
|
1666
|
+
path
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1669
|
+
catch (e) {
|
|
1670
|
+
// 当 Path 存在时,校验 Path 绑定的函数是不是当前函数
|
|
1671
|
+
if (e.code === 'InvalidParameter.APICreated') {
|
|
1672
|
+
const { APISet } = await access.getAccessList({
|
|
1673
|
+
name
|
|
1674
|
+
});
|
|
1675
|
+
if ((APISet === null || APISet === void 0 ? void 0 : APISet[0].Name) !== name || (APISet === null || APISet === void 0 ? void 0 : APISet[0].Type) !== 1) {
|
|
1676
|
+
throw e;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
else {
|
|
1680
|
+
throw e;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1628
1684
|
// 获取 COS 临时信息
|
|
1629
1685
|
async getTempCosInfo(name) {
|
|
1630
1686
|
const { env, appId } = await this.getFunctionConfig();
|
|
@@ -1755,6 +1811,9 @@ __decorate([
|
|
|
1755
1811
|
__decorate([
|
|
1756
1812
|
(0, utils_1.preLazy)()
|
|
1757
1813
|
], FunctionService.prototype, "updateFunctionCode", null);
|
|
1814
|
+
__decorate([
|
|
1815
|
+
(0, utils_1.preLazy)()
|
|
1816
|
+
], FunctionService.prototype, "updateFunctionWithProgress", null);
|
|
1758
1817
|
__decorate([
|
|
1759
1818
|
(0, utils_1.preLazy)()
|
|
1760
1819
|
], FunctionService.prototype, "invokeFunction", null);
|
|
@@ -1829,10 +1888,10 @@ __decorate([
|
|
|
1829
1888
|
], FunctionService.prototype, "uploadFunctionZipToCos", null);
|
|
1830
1889
|
__decorate([
|
|
1831
1890
|
(0, utils_1.preLazy)()
|
|
1832
|
-
], FunctionService.prototype, "
|
|
1891
|
+
], FunctionService.prototype, "getCodeParams", null);
|
|
1833
1892
|
__decorate([
|
|
1834
1893
|
(0, utils_1.preLazy)()
|
|
1835
|
-
], FunctionService.prototype, "
|
|
1894
|
+
], FunctionService.prototype, "createAccessPath", null);
|
|
1836
1895
|
__decorate([
|
|
1837
1896
|
(0, utils_1.preLazy)()
|
|
1838
1897
|
], FunctionService.prototype, "getTempCosInfo", null);
|
package/lib/index.js
CHANGED
|
@@ -79,12 +79,18 @@ class CloudBase {
|
|
|
79
79
|
get env() {
|
|
80
80
|
return this.currentEnvironment().getEnvService();
|
|
81
81
|
}
|
|
82
|
+
get log() {
|
|
83
|
+
return this.currentEnvironment().getLogService();
|
|
84
|
+
}
|
|
82
85
|
get third() {
|
|
83
86
|
return this.currentEnvironment().getThirdService();
|
|
84
87
|
}
|
|
85
88
|
get user() {
|
|
86
89
|
return this.currentEnvironment().getUserService();
|
|
87
90
|
}
|
|
91
|
+
get permission() {
|
|
92
|
+
return this.currentEnvironment().getPermissionService();
|
|
93
|
+
}
|
|
88
94
|
get docs() {
|
|
89
95
|
if (!this.docsService) {
|
|
90
96
|
this.docsService = new docs_1.DocsService();
|
package/lib/log/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.LogService = void 0;
|
|
18
|
+
exports.isLogServiceEnabled = isLogServiceEnabled;
|
|
19
|
+
const utils_1 = require("../utils");
|
|
20
|
+
__exportStar(require("./types"), exports);
|
|
21
|
+
/**
|
|
22
|
+
* 纯函数:根据 DescribeEnvs 返回的 LogServices 列表判断日志服务是否已开通。
|
|
23
|
+
* 已开通条件:至少一个条目有有效的 TopicId。
|
|
24
|
+
*/
|
|
25
|
+
function isLogServiceEnabled(logServices) {
|
|
26
|
+
if (!logServices || logServices.length === 0)
|
|
27
|
+
return false;
|
|
28
|
+
return logServices.some(svc => !!svc.TopicId);
|
|
29
|
+
}
|
|
30
|
+
class LogService {
|
|
31
|
+
constructor(environment) {
|
|
32
|
+
this.envId = environment.getEnvId();
|
|
33
|
+
this.cloudService = new utils_1.CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08');
|
|
34
|
+
this.tcbrService = new utils_1.CloudService(environment.cloudBaseContext, 'tcbr', '2022-02-17');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 检查当前环境的日志服务是否已开通
|
|
38
|
+
*
|
|
39
|
+
* 通过 DescribeEnvs 接口获取环境信息,判断 LogServices 字段中是否包含有效的
|
|
40
|
+
* 日志主题(TopicId 不为空)。
|
|
41
|
+
*
|
|
42
|
+
* @returns true 表示已开通,false 表示未开通或开通中
|
|
43
|
+
*/
|
|
44
|
+
async checkLogServiceEnabled() {
|
|
45
|
+
var _a;
|
|
46
|
+
const res = await this.cloudService.request('DescribeEnvs', {
|
|
47
|
+
EnvId: this.envId
|
|
48
|
+
});
|
|
49
|
+
const envInfo = (_a = res === null || res === void 0 ? void 0 : res.EnvList) === null || _a === void 0 ? void 0 : _a[0];
|
|
50
|
+
if (!envInfo) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const logServices = envInfo.LogServices;
|
|
54
|
+
if (!logServices || logServices.length === 0) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// 已开通:LogServiceInfo 中存在有效的日志主题 ID
|
|
58
|
+
return isLogServiceEnabled(logServices);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 开通环境日志服务(异步操作)
|
|
62
|
+
*
|
|
63
|
+
* 调用 CreateEnvResource 接口开通日志资源。
|
|
64
|
+
* 注意:接口调用成功不代表日志资源立即可用,需通过 checkLogServiceEnabled() 轮询确认。
|
|
65
|
+
*
|
|
66
|
+
* @returns 请求 ID
|
|
67
|
+
*/
|
|
68
|
+
async createLogService() {
|
|
69
|
+
return this.cloudService.request('CreateEnvResource', {
|
|
70
|
+
EnvId: this.envId,
|
|
71
|
+
Resources: ['log']
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 搜索 CLS 日志
|
|
76
|
+
*
|
|
77
|
+
* @param params 查询参数,通过 queryString 使用 CLS 原生检索分析语法
|
|
78
|
+
* @returns 日志搜索结果
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* - 纯检索结果在 `LogResults.Results` 中
|
|
82
|
+
* - SQL 分析结果(queryString 含 `| select ...`)在 `LogResults.AnalysisRecords` 中
|
|
83
|
+
* - 详细的 QueryString 语法参考见 README.md
|
|
84
|
+
*/
|
|
85
|
+
async searchClsLog(params) {
|
|
86
|
+
const { queryString, StartTime, EndTime, Limit, Context, Sort, UseLucene, service } = params;
|
|
87
|
+
const requestService = service === 'tcbr' ? this.tcbrService : this.cloudService;
|
|
88
|
+
const requestParams = {
|
|
89
|
+
EnvId: this.envId,
|
|
90
|
+
StartTime,
|
|
91
|
+
EndTime,
|
|
92
|
+
QueryString: queryString,
|
|
93
|
+
Limit,
|
|
94
|
+
Context,
|
|
95
|
+
Sort,
|
|
96
|
+
UseLucene
|
|
97
|
+
};
|
|
98
|
+
// TenantModel 仅 tcb 服务需要,tcbr 不支持该参数
|
|
99
|
+
if (service !== 'tcbr') {
|
|
100
|
+
requestParams.TenantModel = 'public';
|
|
101
|
+
}
|
|
102
|
+
return requestService.request('SearchClsLog', requestParams);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.LogService = LogService;
|
package/lib/log/types.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// =====================================================
|
|
3
|
+
// CLS 日志字段枚举 & Module 查询 Schema
|
|
4
|
+
// =====================================================
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CLS_MODULE_SCHEMA = void 0;
|
|
7
|
+
// =====================================================
|
|
8
|
+
// CLS Module 运行时常量
|
|
9
|
+
// =====================================================
|
|
10
|
+
/**
|
|
11
|
+
* ClsModuleSchema 的运行时版本,用于动态生成查询条件 / MCP tool description
|
|
12
|
+
*
|
|
13
|
+
* - key 与 ClsLogModule 类型保持同步
|
|
14
|
+
* - eventTypes / logTypes 为字符串数组,空数组表示该维度不可过滤
|
|
15
|
+
*/
|
|
16
|
+
exports.CLS_MODULE_SCHEMA = {
|
|
17
|
+
database: { label: '云数据库(文档型)', eventTypes: ['MongoSlowQuery'], logTypes: [] },
|
|
18
|
+
rdb: { label: '云数据库(SQL型)', eventTypes: ['MysqlFreeze', 'MysqlRecover', 'MysqlSlowQuery'], logTypes: [] },
|
|
19
|
+
model: { label: '数据模型', eventTypes: [], logTypes: [] },
|
|
20
|
+
workflow: { label: '审批流', eventTypes: [], logTypes: [] },
|
|
21
|
+
auth: { label: '用户权限', eventTypes: [], logTypes: [] },
|
|
22
|
+
llm: { label: '大模型', eventTypes: [], logTypes: ['llm-tracelog'] },
|
|
23
|
+
app: { label: '应用', eventTypes: ['AppProdPub', 'AppProdDel'], logTypes: [] },
|
|
24
|
+
};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PermissionService = void 0;
|
|
10
|
+
const utils_1 = require("../utils");
|
|
11
|
+
const PERMISSION_BY_RESOURCE = {
|
|
12
|
+
function: ['CUSTOM'],
|
|
13
|
+
storage: ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY', 'CUSTOM'],
|
|
14
|
+
table: ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY'],
|
|
15
|
+
collection: ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY', 'CUSTOM']
|
|
16
|
+
};
|
|
17
|
+
class PermissionService {
|
|
18
|
+
constructor(environment) {
|
|
19
|
+
this.environment = environment;
|
|
20
|
+
this.tcbService = new utils_1.CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08');
|
|
21
|
+
}
|
|
22
|
+
async modifyResourcePermission(options) {
|
|
23
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
24
|
+
const { resourceType, resource, permission, securityRule } = options;
|
|
25
|
+
if (!resourceType || !PERMISSION_BY_RESOURCE[resourceType]) {
|
|
26
|
+
throw new Error('Invalid resourceType');
|
|
27
|
+
}
|
|
28
|
+
if (typeof resource !== 'string' || resource.trim().length === 0) {
|
|
29
|
+
throw new Error('Invalid resource');
|
|
30
|
+
}
|
|
31
|
+
const allowed = PERMISSION_BY_RESOURCE[resourceType];
|
|
32
|
+
if (!allowed.includes(permission)) {
|
|
33
|
+
throw new Error(`Permission ${permission} is not allowed for resourceType ${resourceType}`);
|
|
34
|
+
}
|
|
35
|
+
if (permission === 'CUSTOM') {
|
|
36
|
+
if (typeof securityRule !== 'string' || securityRule.trim().length === 0) {
|
|
37
|
+
throw new Error('securityRule is required when permission is CUSTOM');
|
|
38
|
+
}
|
|
39
|
+
// // 校验 JSON 字符串合法性
|
|
40
|
+
// try {
|
|
41
|
+
// JSON.parse(securityRule)
|
|
42
|
+
// } catch {
|
|
43
|
+
// throw new Error('securityRule must be a valid JSON string')
|
|
44
|
+
// }
|
|
45
|
+
}
|
|
46
|
+
const reqData = {
|
|
47
|
+
EnvId,
|
|
48
|
+
ResourceType: resourceType,
|
|
49
|
+
Resource: resource,
|
|
50
|
+
Permission: permission
|
|
51
|
+
};
|
|
52
|
+
if (permission === 'CUSTOM') {
|
|
53
|
+
reqData.SecurityRule = securityRule;
|
|
54
|
+
}
|
|
55
|
+
return this.tcbService.request('ModifyResourcePermission', reqData);
|
|
56
|
+
}
|
|
57
|
+
async describeResourcePermission(options) {
|
|
58
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
59
|
+
const { resourceType, resources } = options;
|
|
60
|
+
if (!resourceType || !PERMISSION_BY_RESOURCE[resourceType]) {
|
|
61
|
+
throw new Error('Invalid resourceType');
|
|
62
|
+
}
|
|
63
|
+
if (resources !== undefined) {
|
|
64
|
+
if (!Array.isArray(resources)) {
|
|
65
|
+
throw new Error('Invalid resources');
|
|
66
|
+
}
|
|
67
|
+
if (resources.length > 100) {
|
|
68
|
+
throw new Error('resources length must be <= 100');
|
|
69
|
+
}
|
|
70
|
+
const invalid = resources.find(item => typeof item !== 'string' || item.trim().length === 0);
|
|
71
|
+
if (invalid !== undefined) {
|
|
72
|
+
throw new Error('resources contains invalid item');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return this.tcbService.request('DescribeResourcePermission', Object.assign({ EnvId, ResourceType: resourceType }, (resources !== undefined ? { Resources: resources } : {})));
|
|
76
|
+
}
|
|
77
|
+
async createRole(options) {
|
|
78
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
79
|
+
const { roleName, roleIdentity, description, memberUids, policies } = options;
|
|
80
|
+
// RoleName 校验:非空,2-32字符,中文/字母/数字/_-:@.,必须以字母或中文开头
|
|
81
|
+
if (typeof roleName !== 'string' || roleName.trim().length === 0) {
|
|
82
|
+
throw new Error('roleName is required');
|
|
83
|
+
}
|
|
84
|
+
if (roleName.length < 2 || roleName.length > 32) {
|
|
85
|
+
throw new Error('roleName length must be between 2 and 32');
|
|
86
|
+
}
|
|
87
|
+
if (!/^[\u4e00-\u9fa5a-zA-Z]/.test(roleName)) {
|
|
88
|
+
throw new Error('roleName must start with a letter or Chinese character');
|
|
89
|
+
}
|
|
90
|
+
if (!/^[\u4e00-\u9fa5a-zA-Z0-9\-_:@.]+$/.test(roleName)) {
|
|
91
|
+
throw new Error('roleName can only contain Chinese, letters, digits, and -_:@.');
|
|
92
|
+
}
|
|
93
|
+
// RoleIdentity 校验:非空,字母/数字/_-:@.,不能与默认角色标识重复
|
|
94
|
+
if (typeof roleIdentity !== 'string' || roleIdentity.trim().length === 0) {
|
|
95
|
+
throw new Error('roleIdentity is required');
|
|
96
|
+
}
|
|
97
|
+
if (!/^[a-zA-Z0-9\-_:@.]+$/.test(roleIdentity)) {
|
|
98
|
+
throw new Error('roleIdentity can only contain letters, digits, and -_:@.');
|
|
99
|
+
}
|
|
100
|
+
// Description 校验
|
|
101
|
+
if (description !== undefined && description.length > 255) {
|
|
102
|
+
throw new Error('description length must be <= 255');
|
|
103
|
+
}
|
|
104
|
+
// MemberUids 校验
|
|
105
|
+
if (memberUids !== undefined) {
|
|
106
|
+
if (!Array.isArray(memberUids)) {
|
|
107
|
+
throw new Error('memberUids must be an array');
|
|
108
|
+
}
|
|
109
|
+
if (memberUids.length > 100) {
|
|
110
|
+
throw new Error('memberUids length must be <= 100');
|
|
111
|
+
}
|
|
112
|
+
const invalidUid = memberUids.find(uid => typeof uid !== 'string' || uid.trim().length === 0);
|
|
113
|
+
if (invalidUid !== undefined) {
|
|
114
|
+
throw new Error('memberUids contains invalid item');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Policies 校验
|
|
118
|
+
if (policies !== undefined) {
|
|
119
|
+
if (!Array.isArray(policies)) {
|
|
120
|
+
throw new Error('policies must be an array');
|
|
121
|
+
}
|
|
122
|
+
if (policies.length > 50) {
|
|
123
|
+
throw new Error('policies length must be <= 50');
|
|
124
|
+
}
|
|
125
|
+
const invalidPolicy = policies.find(policy => !policy.ResourceType || !policy.Resource);
|
|
126
|
+
if (invalidPolicy !== undefined) {
|
|
127
|
+
throw new Error('each policy must have ResourceType and Resource');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const reqData = {
|
|
131
|
+
EnvId,
|
|
132
|
+
RoleName: roleName,
|
|
133
|
+
RoleIdentity: roleIdentity
|
|
134
|
+
};
|
|
135
|
+
if (description !== undefined) {
|
|
136
|
+
reqData.Description = description;
|
|
137
|
+
}
|
|
138
|
+
if (memberUids !== undefined && memberUids.length > 0) {
|
|
139
|
+
reqData.MemberUids = memberUids;
|
|
140
|
+
}
|
|
141
|
+
if (policies !== undefined && policies.length > 0) {
|
|
142
|
+
reqData.Policies = policies;
|
|
143
|
+
}
|
|
144
|
+
return this.tcbService.request('CreateRole', reqData);
|
|
145
|
+
}
|
|
146
|
+
async describeRoleList(options = {}) {
|
|
147
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
148
|
+
const { pageNumber, pageSize, roleId, roleIdentity, roleName, loadDetails } = options;
|
|
149
|
+
// PageNumber 校验:从1开始
|
|
150
|
+
if (pageNumber !== undefined && (pageNumber < 1 || !Number.isInteger(pageNumber))) {
|
|
151
|
+
throw new Error('pageNumber must be a positive integer');
|
|
152
|
+
}
|
|
153
|
+
// PageSize 校验:默认10,最大100
|
|
154
|
+
if (pageSize !== undefined && (pageSize < 1 || pageSize > 100 || !Number.isInteger(pageSize))) {
|
|
155
|
+
throw new Error('pageSize must be an integer between 1 and 100');
|
|
156
|
+
}
|
|
157
|
+
// RoleId 校验
|
|
158
|
+
if (roleId !== undefined && (typeof roleId !== 'string' || roleId.trim().length === 0)) {
|
|
159
|
+
throw new Error('Invalid roleId');
|
|
160
|
+
}
|
|
161
|
+
// RoleIdentity 校验
|
|
162
|
+
if (roleIdentity !== undefined && (typeof roleIdentity !== 'string' || roleIdentity.trim().length === 0)) {
|
|
163
|
+
throw new Error('Invalid roleIdentity');
|
|
164
|
+
}
|
|
165
|
+
// RoleName 校验
|
|
166
|
+
if (roleName !== undefined && (typeof roleName !== 'string' || roleName.trim().length === 0)) {
|
|
167
|
+
throw new Error('Invalid roleName');
|
|
168
|
+
}
|
|
169
|
+
const reqData = { EnvId };
|
|
170
|
+
if (pageNumber !== undefined) {
|
|
171
|
+
reqData.PageNumber = pageNumber;
|
|
172
|
+
}
|
|
173
|
+
if (pageSize !== undefined) {
|
|
174
|
+
reqData.PageSize = pageSize;
|
|
175
|
+
}
|
|
176
|
+
if (roleId !== undefined) {
|
|
177
|
+
reqData.RoleId = roleId;
|
|
178
|
+
}
|
|
179
|
+
if (roleIdentity !== undefined) {
|
|
180
|
+
reqData.RoleIdentity = roleIdentity;
|
|
181
|
+
}
|
|
182
|
+
if (roleName !== undefined) {
|
|
183
|
+
reqData.RoleName = roleName;
|
|
184
|
+
}
|
|
185
|
+
if (loadDetails !== undefined) {
|
|
186
|
+
reqData.LoadDetails = loadDetails;
|
|
187
|
+
}
|
|
188
|
+
return this.tcbService.request('DescribeRoleList', reqData);
|
|
189
|
+
}
|
|
190
|
+
async modifyRole(options) {
|
|
191
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
192
|
+
const { roleId, roleName, description, addMemberUids, removeMemberUids, addPolicies, removePolicies } = options;
|
|
193
|
+
// RoleId 校验:必填
|
|
194
|
+
if (typeof roleId !== 'string' || roleId.trim().length === 0) {
|
|
195
|
+
throw new Error('roleId is required');
|
|
196
|
+
}
|
|
197
|
+
// RoleName 校验:不传或传空 => 不修改;非空时校验规则
|
|
198
|
+
if (roleName !== undefined && roleName !== '') {
|
|
199
|
+
if (roleName.length < 2 || roleName.length > 32) {
|
|
200
|
+
throw new Error('roleName length must be between 2 and 32');
|
|
201
|
+
}
|
|
202
|
+
if (!/^[\u4e00-\u9fa5a-zA-Z]/.test(roleName)) {
|
|
203
|
+
throw new Error('roleName must start with a letter or Chinese character');
|
|
204
|
+
}
|
|
205
|
+
if (!/^[\u4e00-\u9fa5a-zA-Z0-9\-_:@.]+$/.test(roleName)) {
|
|
206
|
+
throw new Error('roleName can only contain Chinese, letters, digits, and -_:@.');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Description 校验
|
|
210
|
+
if (description !== undefined && description.length > 255) {
|
|
211
|
+
throw new Error('description length must be <= 255');
|
|
212
|
+
}
|
|
213
|
+
// AddMemberUids 校验
|
|
214
|
+
if (addMemberUids !== undefined) {
|
|
215
|
+
if (!Array.isArray(addMemberUids)) {
|
|
216
|
+
throw new Error('addMemberUids must be an array');
|
|
217
|
+
}
|
|
218
|
+
const invalidUid = addMemberUids.find(uid => typeof uid !== 'string' || uid.trim().length === 0);
|
|
219
|
+
if (invalidUid !== undefined) {
|
|
220
|
+
throw new Error('addMemberUids contains invalid item');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// RemoveMemberUids 校验
|
|
224
|
+
if (removeMemberUids !== undefined) {
|
|
225
|
+
if (!Array.isArray(removeMemberUids)) {
|
|
226
|
+
throw new Error('removeMemberUids must be an array');
|
|
227
|
+
}
|
|
228
|
+
const invalidUid = removeMemberUids.find(uid => typeof uid !== 'string' || uid.trim().length === 0);
|
|
229
|
+
if (invalidUid !== undefined) {
|
|
230
|
+
throw new Error('removeMemberUids contains invalid item');
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// AddPolicies 校验
|
|
234
|
+
if (addPolicies !== undefined) {
|
|
235
|
+
if (!Array.isArray(addPolicies)) {
|
|
236
|
+
throw new Error('addPolicies must be an array');
|
|
237
|
+
}
|
|
238
|
+
const invalidPolicy = addPolicies.find(policy => !policy.ResourceType || !policy.Resource);
|
|
239
|
+
if (invalidPolicy !== undefined) {
|
|
240
|
+
throw new Error('each addPolicy must have ResourceType and Resource');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// RemovePolicies 校验
|
|
244
|
+
if (removePolicies !== undefined) {
|
|
245
|
+
if (!Array.isArray(removePolicies)) {
|
|
246
|
+
throw new Error('removePolicies must be an array');
|
|
247
|
+
}
|
|
248
|
+
const invalidPolicy = removePolicies.find(policy => !policy.ResourceType || !policy.Resource);
|
|
249
|
+
if (invalidPolicy !== undefined) {
|
|
250
|
+
throw new Error('each removePolicy must have ResourceType and Resource');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const reqData = { EnvId, RoleId: roleId };
|
|
254
|
+
// RoleName:不传或传空 => 不修改(不下发)
|
|
255
|
+
if (roleName !== undefined && roleName !== '') {
|
|
256
|
+
reqData.RoleName = roleName;
|
|
257
|
+
}
|
|
258
|
+
if (description !== undefined) {
|
|
259
|
+
reqData.Description = description;
|
|
260
|
+
}
|
|
261
|
+
if (addMemberUids !== undefined) {
|
|
262
|
+
reqData.AddMemberUids = addMemberUids;
|
|
263
|
+
}
|
|
264
|
+
if (removeMemberUids !== undefined) {
|
|
265
|
+
reqData.RemoveMemberUids = removeMemberUids;
|
|
266
|
+
}
|
|
267
|
+
if (addPolicies !== undefined) {
|
|
268
|
+
reqData.AddPolicies = addPolicies;
|
|
269
|
+
}
|
|
270
|
+
if (removePolicies !== undefined) {
|
|
271
|
+
reqData.RemovePolicies = removePolicies;
|
|
272
|
+
}
|
|
273
|
+
return this.tcbService.request('ModifyRole', reqData);
|
|
274
|
+
}
|
|
275
|
+
async deleteRoles(options) {
|
|
276
|
+
const { EnvId } = this.environment.lazyEnvironmentConfig;
|
|
277
|
+
const { roleIds } = options;
|
|
278
|
+
// RoleIds 校验:必填数组,最多100个
|
|
279
|
+
if (!Array.isArray(roleIds) || roleIds.length === 0) {
|
|
280
|
+
throw new Error('roleIds is required and must be a non-empty array');
|
|
281
|
+
}
|
|
282
|
+
if (roleIds.length > 100) {
|
|
283
|
+
throw new Error('roleIds length must be <= 100');
|
|
284
|
+
}
|
|
285
|
+
const invalidId = roleIds.find(id => typeof id !== 'string' || id.trim().length === 0);
|
|
286
|
+
if (invalidId !== undefined) {
|
|
287
|
+
throw new Error('roleIds contains invalid item');
|
|
288
|
+
}
|
|
289
|
+
return this.tcbService.request('DeleteRoles', {
|
|
290
|
+
EnvId,
|
|
291
|
+
RoleIds: roleIds
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
exports.PermissionService = PermissionService;
|
|
296
|
+
__decorate([
|
|
297
|
+
(0, utils_1.preLazy)()
|
|
298
|
+
], PermissionService.prototype, "modifyResourcePermission", null);
|
|
299
|
+
__decorate([
|
|
300
|
+
(0, utils_1.preLazy)()
|
|
301
|
+
], PermissionService.prototype, "describeResourcePermission", null);
|
|
302
|
+
__decorate([
|
|
303
|
+
(0, utils_1.preLazy)()
|
|
304
|
+
], PermissionService.prototype, "createRole", null);
|
|
305
|
+
__decorate([
|
|
306
|
+
(0, utils_1.preLazy)()
|
|
307
|
+
], PermissionService.prototype, "describeRoleList", null);
|
|
308
|
+
__decorate([
|
|
309
|
+
(0, utils_1.preLazy)()
|
|
310
|
+
], PermissionService.prototype, "modifyRole", null);
|
|
311
|
+
__decorate([
|
|
312
|
+
(0, utils_1.preLazy)()
|
|
313
|
+
], PermissionService.prototype, "deleteRoles", null);
|