@cloudbase/manager-node 4.2.3 → 4.2.5
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/CHANGELOG.md +4 -0
- package/lib/constant.js +5 -1
- package/lib/env/index.js +10 -209
- package/lib/function/index.js +0 -3
- package/lib/storage/index.js +24 -10
- package/lib/utils/cloud-api-request.js +7 -0
- package/lib/utils/http-request.js +3 -3
- package/lib/utils/runenv.js +8 -0
- package/package.json +4 -3
- package/types/constant.d.ts +7 -0
- package/types/env/index.d.ts +0 -17
- package/types/function/types.d.ts +0 -2
- package/types/utils/runenv.d.ts +1 -0
- package/src/access/index.ts +0 -168
- package/src/access/types.ts +0 -55
- package/src/billing/index.ts +0 -43
- package/src/cam/index.ts +0 -106
- package/src/cloudBaseRun/index.ts +0 -40
- package/src/cloudBaseRun/types.ts +0 -24
- package/src/common/index.ts +0 -54
- package/src/constant.ts +0 -56
- package/src/context.ts +0 -18
- package/src/database/index.ts +0 -369
- package/src/debug.ts +0 -34
- package/src/env/index.ts +0 -614
- package/src/environment.ts +0 -156
- package/src/environmentManager.ts +0 -50
- package/src/error.ts +0 -27
- package/src/function/index.ts +0 -1378
- package/src/function/packer.ts +0 -164
- package/src/function/types.ts +0 -165
- package/src/hosting/index.ts +0 -698
- package/src/index.ts +0 -127
- package/src/interfaces/base.interface.ts +0 -8
- package/src/interfaces/billing.interface.ts +0 -21
- package/src/interfaces/cam.interface.ts +0 -28
- package/src/interfaces/flexdb.interface.ts +0 -104
- package/src/interfaces/function.interface.ts +0 -75
- package/src/interfaces/index.ts +0 -7
- package/src/interfaces/storage.interface.ts +0 -29
- package/src/interfaces/tcb.interface.ts +0 -642
- package/src/storage/index.ts +0 -1290
- package/src/third/index.ts +0 -24
- package/src/user/index.ts +0 -174
- package/src/user/types.ts +0 -21
- package/src/utils/auth.ts +0 -112
- package/src/utils/cloud-api-request.ts +0 -252
- package/src/utils/cloudbase-request.ts +0 -109
- package/src/utils/envLazy.ts +0 -15
- package/src/utils/fs.ts +0 -57
- package/src/utils/http-request.ts +0 -37
- package/src/utils/index.ts +0 -103
- package/src/utils/parallel.ts +0 -82
- package/src/utils/uuid.ts +0 -14
package/src/third/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Environment } from '../environment'
|
|
2
|
-
import { CloudService } from '../utils'
|
|
3
|
-
|
|
4
|
-
export class ThirdService {
|
|
5
|
-
private cloudService: CloudService
|
|
6
|
-
|
|
7
|
-
constructor(environment: Environment) {
|
|
8
|
-
this.cloudService = new CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// 解除第三方小程序绑定
|
|
12
|
-
async deleteThirdPartAttach(options: {
|
|
13
|
-
ThirdPartAppid: string
|
|
14
|
-
TypeFlag: number
|
|
15
|
-
}): Promise<{
|
|
16
|
-
RequestId: string
|
|
17
|
-
}> {
|
|
18
|
-
const { ThirdPartAppid, TypeFlag } = options
|
|
19
|
-
return this.cloudService.request('DeleteThirdPartAttach', {
|
|
20
|
-
ThirdPartAppid,
|
|
21
|
-
TypeFlag
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
}
|
package/src/user/index.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { Environment } from '../environment'
|
|
2
|
-
import { CloudService, preLazy } from '../utils'
|
|
3
|
-
import { EndUserInfo , EndUserStatus } from './types'
|
|
4
|
-
|
|
5
|
-
export class UserService {
|
|
6
|
-
private environment: Environment
|
|
7
|
-
private tcbService: CloudService
|
|
8
|
-
|
|
9
|
-
constructor(environment: Environment) {
|
|
10
|
-
this.environment = environment
|
|
11
|
-
this.tcbService = new CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08')
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 获取云开发用户列表
|
|
15
|
-
@preLazy()
|
|
16
|
-
public async getEndUserList(options: {
|
|
17
|
-
limit: number,
|
|
18
|
-
offset: number,
|
|
19
|
-
}) {
|
|
20
|
-
const { limit, offset } = options
|
|
21
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
22
|
-
|
|
23
|
-
return this.tcbService.request<{
|
|
24
|
-
Total: number
|
|
25
|
-
Users: EndUserInfo[]
|
|
26
|
-
RequestId: string
|
|
27
|
-
}>('DescribeEndUsers', {
|
|
28
|
-
EnvId,
|
|
29
|
-
Limit: limit,
|
|
30
|
-
Offset: offset
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// // 停用云开发用户
|
|
35
|
-
// @preLazy()
|
|
36
|
-
// public async disableEndUser(options: {
|
|
37
|
-
// uuid: string
|
|
38
|
-
// }) {
|
|
39
|
-
// const { uuid } = options
|
|
40
|
-
// const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
41
|
-
|
|
42
|
-
// return this.tcbService.request<{
|
|
43
|
-
// RequestId: string
|
|
44
|
-
// }>('ModifyEndUser', {
|
|
45
|
-
// EnvId,
|
|
46
|
-
// UUId: uuid,
|
|
47
|
-
// Status: 'DISABLE'
|
|
48
|
-
// })
|
|
49
|
-
// }
|
|
50
|
-
|
|
51
|
-
// 设置云开发用户状态(停用或启用)
|
|
52
|
-
@preLazy()
|
|
53
|
-
public async setEndUserStatus(options: {
|
|
54
|
-
uuid: string,
|
|
55
|
-
status: EndUserStatus
|
|
56
|
-
}) {
|
|
57
|
-
const { uuid, status } = options
|
|
58
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
59
|
-
|
|
60
|
-
return this.tcbService.request<{
|
|
61
|
-
RequestId: string
|
|
62
|
-
}>('ModifyEndUser', {
|
|
63
|
-
EnvId,
|
|
64
|
-
UUId: uuid,
|
|
65
|
-
Status: status
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 批量删除云开发用户
|
|
70
|
-
@preLazy()
|
|
71
|
-
public async deleteEndUsers(options: {
|
|
72
|
-
userList: string[]
|
|
73
|
-
}) {
|
|
74
|
-
const { userList } = options
|
|
75
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
76
|
-
|
|
77
|
-
return this.tcbService.request<{
|
|
78
|
-
RequestId: string
|
|
79
|
-
}>('DeleteEndUser', {
|
|
80
|
-
EnvId,
|
|
81
|
-
UserList: userList
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 创建用户名密码
|
|
86
|
-
@preLazy()
|
|
87
|
-
public async createEndUser(options: {
|
|
88
|
-
username: string
|
|
89
|
-
password: string
|
|
90
|
-
}) {
|
|
91
|
-
const { username, password } = options
|
|
92
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
93
|
-
|
|
94
|
-
return this.tcbService.request<{
|
|
95
|
-
RequestId: string,
|
|
96
|
-
User: EndUserInfo
|
|
97
|
-
}>('CreateEndUserAccount', {
|
|
98
|
-
EnvId,
|
|
99
|
-
Username: username,
|
|
100
|
-
Password: password,
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// 更改用户账户
|
|
105
|
-
@preLazy()
|
|
106
|
-
public async modifyEndUser(options: {
|
|
107
|
-
uuid: string,
|
|
108
|
-
password?: string,
|
|
109
|
-
username?: string
|
|
110
|
-
}) {
|
|
111
|
-
const { uuid, username, password } = options
|
|
112
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
113
|
-
|
|
114
|
-
const reqData: any = {
|
|
115
|
-
EnvId,
|
|
116
|
-
Uuid: uuid
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (this.isValidStr(username)) {
|
|
120
|
-
reqData.Username = username
|
|
121
|
-
}
|
|
122
|
-
if (this.isValidStr(password)) {
|
|
123
|
-
reqData.Password = password
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return this.tcbService.request<{
|
|
127
|
-
RequestId: string
|
|
128
|
-
}>('ModifyEndUserAccount', reqData)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// 更改用户信息
|
|
132
|
-
@preLazy()
|
|
133
|
-
public async updateEndUser(options: {
|
|
134
|
-
uuid: string,
|
|
135
|
-
nickName: string,
|
|
136
|
-
gender: string,
|
|
137
|
-
avatarUrl: string,
|
|
138
|
-
country: string,
|
|
139
|
-
province: string,
|
|
140
|
-
city: string
|
|
141
|
-
}) {
|
|
142
|
-
const { uuid, nickName, gender, avatarUrl, country, province, city } = options
|
|
143
|
-
const { EnvId } = this.environment.lazyEnvironmentConfig
|
|
144
|
-
|
|
145
|
-
return this.tcbService.request<{
|
|
146
|
-
RequestId: string
|
|
147
|
-
}>('ModifyEndUserInfo', {
|
|
148
|
-
UUId: uuid,
|
|
149
|
-
EnvId,
|
|
150
|
-
Data: [{
|
|
151
|
-
Key: 'Name',
|
|
152
|
-
Value: nickName
|
|
153
|
-
},{
|
|
154
|
-
Key: 'Gender',
|
|
155
|
-
Value: gender
|
|
156
|
-
},{
|
|
157
|
-
Key: 'AvatarUrl',
|
|
158
|
-
Value: avatarUrl
|
|
159
|
-
},{
|
|
160
|
-
Key: 'Country',
|
|
161
|
-
Value: country
|
|
162
|
-
},{
|
|
163
|
-
Key: 'Province',
|
|
164
|
-
Value: province
|
|
165
|
-
},{
|
|
166
|
-
Key: 'City',
|
|
167
|
-
Value: city
|
|
168
|
-
}]})
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private isValidStr(obj: any) {
|
|
172
|
-
return typeof obj === 'string' && obj.trim().length > 0
|
|
173
|
-
}
|
|
174
|
-
}
|
package/src/user/types.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export interface EndUserInfo {
|
|
2
|
-
UUId: string
|
|
3
|
-
WXOpenId: string
|
|
4
|
-
QQOpenId: string
|
|
5
|
-
Phone: string
|
|
6
|
-
Email: string
|
|
7
|
-
NickName: string
|
|
8
|
-
Gender: string
|
|
9
|
-
AvatarUrl: string
|
|
10
|
-
Country: string
|
|
11
|
-
Province: string
|
|
12
|
-
City: string
|
|
13
|
-
UpdateTime: string
|
|
14
|
-
CreateTime: string
|
|
15
|
-
IsAnonymous: boolean
|
|
16
|
-
IsDisabled: boolean
|
|
17
|
-
HasPassword: boolean
|
|
18
|
-
UserName: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type EndUserStatus = 'ENABLE' | 'DISABLE'
|
package/src/utils/auth.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto'
|
|
2
|
-
|
|
3
|
-
function camSafeUrlEncode(str) {
|
|
4
|
-
return encodeURIComponent(str)
|
|
5
|
-
.replace(/!/g, '%21')
|
|
6
|
-
.replace(/'/g, '%27')
|
|
7
|
-
.replace(/\(/g, '%28')
|
|
8
|
-
.replace(/\)/g, '%29')
|
|
9
|
-
.replace(/\*/g, '%2A')
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function getAuth(options: {
|
|
13
|
-
secretId: string
|
|
14
|
-
secretKey: string
|
|
15
|
-
method: string
|
|
16
|
-
pathname?: string
|
|
17
|
-
params?: Record<string, any>
|
|
18
|
-
headers?: Record<string, any>
|
|
19
|
-
}) {
|
|
20
|
-
const SecretId = options.secretId
|
|
21
|
-
const SecretKey = options.secretKey
|
|
22
|
-
const method = options.method.toLowerCase() || 'get'
|
|
23
|
-
const queryParams = options.params || {}
|
|
24
|
-
const headers = options.headers || {}
|
|
25
|
-
let pathname = options.pathname || '/'
|
|
26
|
-
pathname.indexOf('/') !== 0 && (pathname = '/' + pathname)
|
|
27
|
-
|
|
28
|
-
if (!SecretId) {
|
|
29
|
-
throw Error('missing param SecretId')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (!SecretKey) {
|
|
33
|
-
throw Error('missing param SecretKey')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const getObjectKeys = function(obj) {
|
|
37
|
-
return Object.keys(obj)
|
|
38
|
-
.filter(key => typeof obj[key] !== 'undefined')
|
|
39
|
-
.sort()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const objectToString = function(obj) {
|
|
43
|
-
const list = []
|
|
44
|
-
const keyList = getObjectKeys(obj)
|
|
45
|
-
keyList.forEach(key => {
|
|
46
|
-
let value = obj[key] === null || typeof obj[key] === 'undefined' ? '' : obj[key]
|
|
47
|
-
if (typeof value !== 'string') {
|
|
48
|
-
value = JSON.stringify(value)
|
|
49
|
-
}
|
|
50
|
-
list.push(`${camSafeUrlEncode(key.toLowerCase())}=${camSafeUrlEncode(value)}`)
|
|
51
|
-
})
|
|
52
|
-
return list.join('&')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// 签名有效起止时间
|
|
56
|
-
const now = Math.floor(Date.now() / 1000) - 1
|
|
57
|
-
// 签名过期时间为当前 + 900s
|
|
58
|
-
const exp = now + 900
|
|
59
|
-
|
|
60
|
-
// 要用到的 Authorization 参数列表
|
|
61
|
-
const qSignAlgorithm = 'sha1'
|
|
62
|
-
const qAk = SecretId
|
|
63
|
-
const qKeyTime = now + ';' + exp
|
|
64
|
-
const qHeaderList = getObjectKeys(headers)
|
|
65
|
-
.join(';')
|
|
66
|
-
.toLowerCase()
|
|
67
|
-
|
|
68
|
-
const qUrlParamList = getObjectKeys(queryParams)
|
|
69
|
-
.join(';')
|
|
70
|
-
.toLowerCase()
|
|
71
|
-
|
|
72
|
-
// 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
|
|
73
|
-
// 步骤一:计算 SignKey
|
|
74
|
-
const signKey = crypto
|
|
75
|
-
.createHmac('sha1', SecretKey)
|
|
76
|
-
.update(qKeyTime)
|
|
77
|
-
.digest('hex')
|
|
78
|
-
|
|
79
|
-
// 步骤二:构成 FormatString
|
|
80
|
-
const formatString = [
|
|
81
|
-
method,
|
|
82
|
-
pathname,
|
|
83
|
-
objectToString(queryParams),
|
|
84
|
-
objectToString(headers),
|
|
85
|
-
''
|
|
86
|
-
].join('\n')
|
|
87
|
-
|
|
88
|
-
// 步骤三:计算 StringToSign
|
|
89
|
-
const sha1Algo = crypto.createHash('sha1')
|
|
90
|
-
sha1Algo.update(Buffer.from(formatString))
|
|
91
|
-
const res = sha1Algo.digest('hex')
|
|
92
|
-
const stringToSign = ['sha1', qKeyTime, res, ''].join('\n')
|
|
93
|
-
|
|
94
|
-
// 步骤四:计算 Signature
|
|
95
|
-
const qSignature = crypto
|
|
96
|
-
.createHmac('sha1', signKey)
|
|
97
|
-
.update(stringToSign)
|
|
98
|
-
.digest('hex')
|
|
99
|
-
|
|
100
|
-
// 步骤五:构造 Authorization
|
|
101
|
-
const authorization = [
|
|
102
|
-
'q-sign-algorithm=' + qSignAlgorithm,
|
|
103
|
-
'q-ak=' + qAk,
|
|
104
|
-
'q-sign-time=' + qKeyTime,
|
|
105
|
-
'q-key-time=' + qKeyTime,
|
|
106
|
-
'q-header-list=' + qHeaderList,
|
|
107
|
-
'q-url-param-list=' + qUrlParamList,
|
|
108
|
-
'q-signature=' + qSignature
|
|
109
|
-
].join('&')
|
|
110
|
-
|
|
111
|
-
return authorization
|
|
112
|
-
}
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto'
|
|
2
|
-
import { URL } from 'url'
|
|
3
|
-
import QueryString from 'query-string'
|
|
4
|
-
import { CloudBaseError } from '../error'
|
|
5
|
-
import { CloudBaseContext } from '../context'
|
|
6
|
-
import { fetch } from './http-request'
|
|
7
|
-
import { RUN_ENV, ENV_NAME, ERROR } from '../constant'
|
|
8
|
-
import { getRuntime, getEnvVar } from '../utils'
|
|
9
|
-
|
|
10
|
-
function isObject(x) {
|
|
11
|
-
return typeof x === 'object' && !Array.isArray(x) && x !== null
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 移除对象中的空值
|
|
15
|
-
function deepRemoveVoid(obj) {
|
|
16
|
-
if (Array.isArray(obj)) {
|
|
17
|
-
return obj.map(deepRemoveVoid)
|
|
18
|
-
} else if (isObject(obj)) {
|
|
19
|
-
let result = {}
|
|
20
|
-
for (let key in obj) {
|
|
21
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
22
|
-
const value = obj[key]
|
|
23
|
-
if (typeof value !== 'undefined' && value !== null) {
|
|
24
|
-
result[key] = deepRemoveVoid(value)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return result
|
|
29
|
-
} else {
|
|
30
|
-
return obj
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type HexBase64Latin1Encoding = 'latin1' | 'hex' | 'base64'
|
|
35
|
-
|
|
36
|
-
function sha256(message: string, secret: string, encoding?: HexBase64Latin1Encoding) {
|
|
37
|
-
const hmac = crypto.createHmac('sha256', secret)
|
|
38
|
-
return hmac.update(message).digest(encoding)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function getHash(message: string): string {
|
|
42
|
-
const hash = crypto.createHash('sha256')
|
|
43
|
-
return hash.update(message).digest('hex')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function getDate(timestamp: number): string {
|
|
47
|
-
const date = new Date(timestamp * 1000)
|
|
48
|
-
const year = date.getUTCFullYear()
|
|
49
|
-
const month = ('0' + (date.getUTCMonth() + 1)).slice(-2)
|
|
50
|
-
// UTC 日期,非本地时间
|
|
51
|
-
const day = ('0' + date.getUTCDate()).slice(-2)
|
|
52
|
-
return `${year}-${month}-${day}`
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class CloudService {
|
|
56
|
-
service: string
|
|
57
|
-
version: string
|
|
58
|
-
url: string
|
|
59
|
-
action: string
|
|
60
|
-
method: 'POST' | 'GET'
|
|
61
|
-
secretId: string //
|
|
62
|
-
secretKey: string //
|
|
63
|
-
token: string //
|
|
64
|
-
timeout: number
|
|
65
|
-
data: Record<string, any>
|
|
66
|
-
payload: Record<string, any>
|
|
67
|
-
baseParams: Record<string, any>
|
|
68
|
-
cloudBaseContext: CloudBaseContext
|
|
69
|
-
|
|
70
|
-
/* eslint-disable-next-line */
|
|
71
|
-
constructor(
|
|
72
|
-
context: CloudBaseContext,
|
|
73
|
-
service: string,
|
|
74
|
-
version: string,
|
|
75
|
-
baseParams?: Record<string, any>
|
|
76
|
-
) {
|
|
77
|
-
this.service = service
|
|
78
|
-
this.version = version
|
|
79
|
-
this.timeout = 60000
|
|
80
|
-
this.baseParams = baseParams || {}
|
|
81
|
-
this.cloudBaseContext = context
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get baseUrl() {
|
|
85
|
-
const tcb = process.env.TCB_BASE_URL || 'https://tcb.tencentcloudapi.com'
|
|
86
|
-
const urlMap = {
|
|
87
|
-
tcb,
|
|
88
|
-
scf: 'https://scf.tencentcloudapi.com',
|
|
89
|
-
vpc: 'https://vpc.tencentcloudapi.com',
|
|
90
|
-
flexdb: 'https://flexdb.tencentcloudapi.com',
|
|
91
|
-
cam: 'https://cam.tencentcloudapi.com',
|
|
92
|
-
cdn: 'https://cdn.tencentcloudapi.com'
|
|
93
|
-
}
|
|
94
|
-
if (urlMap[this.service]) {
|
|
95
|
-
return urlMap[this.service]
|
|
96
|
-
} else {
|
|
97
|
-
return `https://${this.service}.tencentcloudapi.com`
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async request<T extends {}>(
|
|
102
|
-
action: string,
|
|
103
|
-
data: Record<string, any> = {},
|
|
104
|
-
method: 'POST' | 'GET' = 'POST'
|
|
105
|
-
): Promise<T> {
|
|
106
|
-
this.action = action
|
|
107
|
-
this.data = deepRemoveVoid({ ...data, ...this.baseParams })
|
|
108
|
-
this.method = method
|
|
109
|
-
|
|
110
|
-
this.url = this.baseUrl
|
|
111
|
-
|
|
112
|
-
let { secretId, secretKey, token } = this.cloudBaseContext
|
|
113
|
-
|
|
114
|
-
// 当在云函数环境下执行时,可init时不传入密钥,取环境变量中密钥使用
|
|
115
|
-
// request执行时一般处于main函数内部,取环境变量逻辑写这里更可靠
|
|
116
|
-
if (!secretId || !secretKey) {
|
|
117
|
-
// 未主动传入密钥,从环境变量中读取
|
|
118
|
-
const envSecretId = getEnvVar(ENV_NAME.ENV_SECRETID)
|
|
119
|
-
const envSecretKey = getEnvVar(ENV_NAME.ENV_SECRETKEY)
|
|
120
|
-
const envToken = getEnvVar(ENV_NAME.ENV_SESSIONTOKEN)
|
|
121
|
-
if (!envSecretId || !envSecretKey) {
|
|
122
|
-
if (getRuntime() === RUN_ENV.SCF) {
|
|
123
|
-
throw new Error('missing authoration key, redeploy the function')
|
|
124
|
-
} else {
|
|
125
|
-
throw new Error('missing secretId or secretKey of tencent cloud')
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
secretId = envSecretId
|
|
129
|
-
secretKey = envSecretKey
|
|
130
|
-
token = envToken
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
this.secretId = secretId
|
|
135
|
-
this.secretKey = secretKey
|
|
136
|
-
this.token = token
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
const data: Record<string, any> = await this.requestWithSign()
|
|
140
|
-
|
|
141
|
-
if (data.Response.Error) {
|
|
142
|
-
const tcError = new CloudBaseError(data.Response.Error.Message, {
|
|
143
|
-
action,
|
|
144
|
-
requestId: data.Response.RequestId,
|
|
145
|
-
code: data.Response.Error.Code,
|
|
146
|
-
original: data.Response.Error
|
|
147
|
-
})
|
|
148
|
-
throw tcError
|
|
149
|
-
} else {
|
|
150
|
-
return data.Response
|
|
151
|
-
}
|
|
152
|
-
} catch (e) {
|
|
153
|
-
if (e.name === 'CloudBaseError') {
|
|
154
|
-
throw e
|
|
155
|
-
} else {
|
|
156
|
-
throw new CloudBaseError(e.message, {
|
|
157
|
-
action,
|
|
158
|
-
code: e.code
|
|
159
|
-
})
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async requestWithSign() {
|
|
165
|
-
// data 中可能带有 readStream,由于需要计算整个 body 的 hash,
|
|
166
|
-
// 所以这里把 readStream 转为 Buffer
|
|
167
|
-
// await convertReadStreamToBuffer(data)
|
|
168
|
-
const timestamp = Math.floor(new Date().getTime() / 1000)
|
|
169
|
-
const { proxy } = this.cloudBaseContext
|
|
170
|
-
|
|
171
|
-
const { method, timeout, data = {} } = this
|
|
172
|
-
|
|
173
|
-
if (method === 'GET') {
|
|
174
|
-
this.url += '?' + QueryString.stringify(data)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (method === 'POST') {
|
|
178
|
-
this.payload = data
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const config: any = {
|
|
182
|
-
method,
|
|
183
|
-
timeout,
|
|
184
|
-
headers: {
|
|
185
|
-
Host: new URL(this.url).host,
|
|
186
|
-
'X-TC-Action': this.action,
|
|
187
|
-
// region 优先级 mock本地注入 > init 指定 > 云函数环境变量
|
|
188
|
-
'X-TC-Region':
|
|
189
|
-
process.env.TCB_REGION ||
|
|
190
|
-
this.cloudBaseContext.region ||
|
|
191
|
-
process.env.TENCENTCLOUD_REGION ||
|
|
192
|
-
'ap-shanghai',
|
|
193
|
-
'X-TC-Timestamp': timestamp,
|
|
194
|
-
'X-TC-Version': this.version
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (this.token) {
|
|
199
|
-
config.headers['X-TC-Token'] = this.token
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (method === 'GET') {
|
|
203
|
-
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
204
|
-
}
|
|
205
|
-
if (method === 'POST') {
|
|
206
|
-
config.body = JSON.stringify(data)
|
|
207
|
-
config.headers['Content-Type'] = 'application/json'
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const sign = this.getRequestSign(timestamp)
|
|
211
|
-
|
|
212
|
-
config.headers['Authorization'] = sign
|
|
213
|
-
|
|
214
|
-
return fetch(this.url, config, proxy)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
getRequestSign(timestamp: number) {
|
|
218
|
-
const { method = 'POST', url, service, secretId, secretKey } = this
|
|
219
|
-
const urlObj = new URL(url)
|
|
220
|
-
|
|
221
|
-
// 通用头部
|
|
222
|
-
let headers = ''
|
|
223
|
-
const signedHeaders = 'content-type;host'
|
|
224
|
-
if (method === 'GET') {
|
|
225
|
-
headers = 'content-type:application/x-www-form-urlencoded\n'
|
|
226
|
-
} else if (method === 'POST') {
|
|
227
|
-
headers = 'content-type:application/json\n'
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
headers += `host:${urlObj.hostname}\n`
|
|
231
|
-
|
|
232
|
-
const path = urlObj.pathname
|
|
233
|
-
const querystring = urlObj.search.slice(1)
|
|
234
|
-
|
|
235
|
-
const payloadHash = this.payload ? getHash(JSON.stringify(this.payload)) : getHash('')
|
|
236
|
-
|
|
237
|
-
const canonicalRequest = `${method}\n${path}\n${querystring}\n${headers}\n${signedHeaders}\n${payloadHash}`
|
|
238
|
-
|
|
239
|
-
const date = getDate(timestamp)
|
|
240
|
-
|
|
241
|
-
const StringToSign = `TC3-HMAC-SHA256\n${timestamp}\n${date}/${service}/tc3_request\n${getHash(
|
|
242
|
-
canonicalRequest
|
|
243
|
-
)}`
|
|
244
|
-
|
|
245
|
-
const kDate = sha256(date, `TC3${secretKey}`)
|
|
246
|
-
const kService = sha256(service, kDate)
|
|
247
|
-
const kSigning = sha256('tc3_request', kService)
|
|
248
|
-
const signature = sha256(StringToSign, kSigning, 'hex')
|
|
249
|
-
|
|
250
|
-
return `TC3-HMAC-SHA256 Credential=${secretId}/${date}/${service}/tc3_request, SignedHeaders=${signedHeaders}, Signature=${signature}`
|
|
251
|
-
}
|
|
252
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { getAuth } from './auth'
|
|
2
|
-
import { fetch } from './http-request'
|
|
3
|
-
|
|
4
|
-
const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou']
|
|
5
|
-
|
|
6
|
-
export async function cloudBaseRequest(options: {
|
|
7
|
-
config: {
|
|
8
|
-
envId: string
|
|
9
|
-
secretId: string
|
|
10
|
-
secretKey: string
|
|
11
|
-
token?: string
|
|
12
|
-
timeout?: number
|
|
13
|
-
proxy: string
|
|
14
|
-
region: string
|
|
15
|
-
}
|
|
16
|
-
params: Record<string, any>
|
|
17
|
-
method?: string
|
|
18
|
-
headers?: Record<string, any>
|
|
19
|
-
}) {
|
|
20
|
-
// const url = 'https://tcb-admin.tencentcloudapi.com/admin'
|
|
21
|
-
const { config, params = {}, method = 'POST', headers = {} } = options
|
|
22
|
-
const { region, envId } = config
|
|
23
|
-
const isInScf = process.env.TENCENTCLOUD_RUNENV === 'SCF' // 是否scf环境内
|
|
24
|
-
const protocol = isInScf ? 'http' : 'https'
|
|
25
|
-
const isInContainer = !!process.env.KUBERNETES_SERVICE_HOST // 是否容器环境
|
|
26
|
-
// region 优先级 本地mock 注入 > init region > 云函数环境变量region
|
|
27
|
-
const finalRegion = process.env.TCB_REGION || region || process.env.TENCENTCLOUD_REGION || ''
|
|
28
|
-
let internetRegionEndpoint = ''
|
|
29
|
-
let internalRegionEndpoint = ''
|
|
30
|
-
if (finalRegion) {
|
|
31
|
-
if (SUPPORT_REGIONS.includes(finalRegion)) {
|
|
32
|
-
internetRegionEndpoint = `${finalRegion}.tcb-api.tencentcloudapi.com`
|
|
33
|
-
internalRegionEndpoint = `internal.${finalRegion}.tcb-api.tencentcloudapi.com`
|
|
34
|
-
} else {
|
|
35
|
-
console.warn('当前仅支持上海,广州地域,其他地域默认解析到固定域名(上海地域)')
|
|
36
|
-
internetRegionEndpoint = `tcb-api.tencentcloudapi.com`
|
|
37
|
-
internalRegionEndpoint = `internal.tcb-api.tencentcloudapi.com`
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
internetRegionEndpoint = `tcb-api.tencentcloudapi.com`
|
|
41
|
-
internalRegionEndpoint = `internal.tcb-api.tencentcloudapi.com`
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// 有地域信息则访问地域级别域名,无地域信息则访问默认域名,默认域名固定解析到上海地域保持兼容
|
|
45
|
-
// const internetRegionEndpoint = finalRegion
|
|
46
|
-
// ? `${finalRegion}.tcb-api.tencentcloudapi.com`
|
|
47
|
-
// : `tcb-api.tencentcloudapi.com`
|
|
48
|
-
|
|
49
|
-
// const internalRegionEndpoint = finalRegion
|
|
50
|
-
// ? `internal.${finalRegion}.tcb-api.tencentcloudapi.com`
|
|
51
|
-
// : `internal.tcb-api.tencentcloudapi.com`
|
|
52
|
-
|
|
53
|
-
// 同地域走内网,跨地域走公网
|
|
54
|
-
const isSameRegionVisit = region ? region === process.env.TENCENTCLOUD_REGION : true
|
|
55
|
-
|
|
56
|
-
// const endpoint = isInScf || isInContainer ? internalRegionEndpoint : internetRegionEndpoint
|
|
57
|
-
const endpoint =
|
|
58
|
-
isSameRegionVisit && (isInScf || isInContainer)
|
|
59
|
-
? internalRegionEndpoint
|
|
60
|
-
: internetRegionEndpoint
|
|
61
|
-
// const envpoint = envId ? `${envId}.${endpoint}` : endpoint
|
|
62
|
-
const envpoint = endpoint
|
|
63
|
-
|
|
64
|
-
const url = `${protocol}://${envpoint}/admin`
|
|
65
|
-
|
|
66
|
-
const requestData: any = {
|
|
67
|
-
...params,
|
|
68
|
-
envName: config.envId,
|
|
69
|
-
timestamp: Date.now()
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const requestHeaders = {
|
|
73
|
-
...headers,
|
|
74
|
-
'content-type': 'application/json',
|
|
75
|
-
'user-agent': `cloudbase-manager-node/0.1.0`,
|
|
76
|
-
'x-tcb-source': 'cloudbase-manager-node, not-scf'
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const { secretId, secretKey, token, proxy } = config
|
|
80
|
-
|
|
81
|
-
const authData = {
|
|
82
|
-
secretId,
|
|
83
|
-
secretKey,
|
|
84
|
-
method: method,
|
|
85
|
-
pathname: '/admin',
|
|
86
|
-
params: requestData,
|
|
87
|
-
headers: requestHeaders
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const authorization = getAuth(authData)
|
|
91
|
-
|
|
92
|
-
const requestBody = {
|
|
93
|
-
...requestData,
|
|
94
|
-
sessionToken: token,
|
|
95
|
-
authorization
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const res = await fetch(
|
|
99
|
-
url,
|
|
100
|
-
{
|
|
101
|
-
method,
|
|
102
|
-
body: JSON.stringify(requestBody),
|
|
103
|
-
headers: requestHeaders
|
|
104
|
-
},
|
|
105
|
-
process.env.TCB_ADMIN_PROXY || proxy
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
return res
|
|
109
|
-
}
|