free-be-account 0.0.21 → 0.0.22
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/index.js +46 -11
- package/package.json +10 -9
- package/routers/mgmt/route.js +104 -2
- package/routers/perm/route.js +1 -1
- package/sms/index.js +20 -4
- package/sms/platforms/submail.js +70 -0
- package/sms/platforms/tencent.js +73 -0
- package/utils.js +3 -1
package/index.js
CHANGED
|
@@ -27,7 +27,7 @@ try {
|
|
|
27
27
|
let __app_service_list_saved = false;
|
|
28
28
|
let __saved_service_list;
|
|
29
29
|
|
|
30
|
-
const __getServiceList = async (res, filter = { Enabled: true }) => {
|
|
30
|
+
const __getServiceList = async (res, filter = { Enabled: true }, scopeFilter) => {
|
|
31
31
|
// add app.serviceList into db if not yet
|
|
32
32
|
if (!__app_service_list_saved) {
|
|
33
33
|
await res.app.modules.account.utils.saveServiceList(res.app);
|
|
@@ -36,7 +36,7 @@ const __getServiceList = async (res, filter = { Enabled: true }) => {
|
|
|
36
36
|
return __saved_service_list;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const allPerms = await res.app.models.permission.find(filter);
|
|
39
|
+
const allPerms = await res.app.models.permission.find(filter).lean();
|
|
40
40
|
|
|
41
41
|
const permList = {};
|
|
42
42
|
if (allPerms && allPerms.length > 0) {
|
|
@@ -58,18 +58,39 @@ const __getServiceList = async (res, filter = { Enabled: true }) => {
|
|
|
58
58
|
Description: doc.Description,
|
|
59
59
|
Index: doc.Index,
|
|
60
60
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
((doc.Scope || []).length <= 0) ? {} : {
|
|
62
|
+
Scope: doc.Scope.map(sc => {
|
|
63
|
+
const dso = app.getContainerContent('DataScope').find(ds => ds.Name === sc.Name);
|
|
64
|
+
|
|
65
|
+
if (!dso) {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// the final scope options
|
|
70
|
+
let scopeOptions = [];
|
|
71
|
+
|
|
72
|
+
if (!scopeFilter) {
|
|
73
|
+
scopeOptions = dso.Options;
|
|
74
|
+
} else {
|
|
75
|
+
// get the scope filter of the current doc
|
|
76
|
+
const scopeFilterOfTheCurrentDoc = (scopeFilter && scopeFilter[doc.Path]) || {};
|
|
77
|
+
// get the option level of the filter
|
|
78
|
+
const filterOptionValue = scopeFilterOfTheCurrentDoc[sc.Name] || dso.Default;
|
|
79
|
+
const filterOption = dso.Options.find(o => o.Value === filterOptionValue);
|
|
80
|
+
|
|
81
|
+
if (filterOption && (filterOption.Level !== void 0)) {
|
|
82
|
+
scopeOptions = dso.Options.filter(o => (o.Level !== void 0) && (o.Level <= filterOption.Level));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
66
87
|
Label: dso.Label || '',
|
|
67
88
|
Field: `${sc.Name}`,
|
|
68
89
|
Type: dso.Component || 'Select',
|
|
69
|
-
Options:
|
|
90
|
+
Options: scopeOptions || [],
|
|
70
91
|
Multiple: dso.Multiple || false,
|
|
71
|
-
}
|
|
72
|
-
})
|
|
92
|
+
};
|
|
93
|
+
}),
|
|
73
94
|
})
|
|
74
95
|
}
|
|
75
96
|
}
|
|
@@ -637,14 +658,17 @@ module.exports = (app) => ({
|
|
|
637
658
|
{
|
|
638
659
|
Label: mdl.t('Self'),
|
|
639
660
|
Value: 'self',
|
|
661
|
+
Level: 1, // Level越大,越高权限
|
|
640
662
|
},
|
|
641
663
|
{
|
|
642
664
|
Label: mdl.t('My Org'),
|
|
643
665
|
Value: 'org',
|
|
666
|
+
Level: 10,
|
|
644
667
|
},
|
|
645
668
|
{
|
|
646
669
|
Label: mdl.t('All'),
|
|
647
670
|
Value: 'all',
|
|
671
|
+
Level: 20,
|
|
648
672
|
}
|
|
649
673
|
],
|
|
650
674
|
Default: 'self',
|
|
@@ -1139,6 +1163,7 @@ module.exports = (app) => ({
|
|
|
1139
1163
|
|
|
1140
1164
|
res.addData({
|
|
1141
1165
|
Name: (req.user.Profile && req.user.Profile.Name) || req.user.PhoneNumber || req.user.UserName || '',
|
|
1166
|
+
Account: req.user.PhoneNumber || req.user.UserName,
|
|
1142
1167
|
Avatar: req.user.Profile && req.user.Profile.Avatar ? req.user.Profile.Avatar : '',
|
|
1143
1168
|
Status: req.user.Status,
|
|
1144
1169
|
}, false);
|
|
@@ -1451,12 +1476,22 @@ module.exports = (app) => ({
|
|
|
1451
1476
|
}
|
|
1452
1477
|
|
|
1453
1478
|
let filter;
|
|
1479
|
+
let scopeFilter = {};
|
|
1454
1480
|
if (req.user.Permission !== '*') {
|
|
1455
1481
|
const permPathList = getPermissionPathList(req.user.Permission);
|
|
1456
1482
|
filter = { Path: { $in: permPathList } };
|
|
1483
|
+
|
|
1484
|
+
for (let i = 0; i < permPathList.length; i += 1) {
|
|
1485
|
+
const p = permPathList[i];
|
|
1486
|
+
const pScope = Object.nestValue(req.user.Permission, p.replace(/^\//,'').replace(/\//g, '.'));
|
|
1487
|
+
|
|
1488
|
+
if (pScope && pScope.Scope) {
|
|
1489
|
+
scopeFilter[p] = pScope.Scope;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1457
1492
|
}
|
|
1458
1493
|
|
|
1459
|
-
res.addData(await __getServiceList(res, filter));
|
|
1494
|
+
res.addData(await __getServiceList(res, filter, scopeFilter));
|
|
1460
1495
|
|
|
1461
1496
|
return next();
|
|
1462
1497
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "free-be-account",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -8,20 +8,21 @@
|
|
|
8
8
|
"url": "https://github.com/freeeis/free-be-account.git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@alicloud/pop-core": "^1.
|
|
12
|
-
"axios": "^1.
|
|
13
|
-
"bcrypt": "^
|
|
14
|
-
"connect-redis": "^
|
|
11
|
+
"@alicloud/pop-core": "^1.8.0",
|
|
12
|
+
"axios": "^1.10.0",
|
|
13
|
+
"bcrypt": "^6.0.0",
|
|
14
|
+
"connect-redis": "^8.1.0",
|
|
15
15
|
"crypto-js": "^4.2.0",
|
|
16
16
|
"express-session": "^1.18.1",
|
|
17
17
|
"js-md5": "^0.8.3",
|
|
18
|
-
"minimatch": "^10.0.
|
|
19
|
-
"nodemailer": "^
|
|
18
|
+
"minimatch": "^10.0.3",
|
|
19
|
+
"nodemailer": "^7.0.4",
|
|
20
20
|
"passport": "^0.7.0",
|
|
21
21
|
"passport-local": "^1.0.0",
|
|
22
|
-
"semver": "^7.
|
|
22
|
+
"semver": "^7.7.2",
|
|
23
23
|
"svg-captcha": "^1.4.0",
|
|
24
24
|
"tar": "^7.4.3",
|
|
25
|
-
"
|
|
25
|
+
"tencentcloud-sdk-nodejs-sms": "^4.1.71",
|
|
26
|
+
"uuid": "^11.1.0"
|
|
26
27
|
}
|
|
27
28
|
}
|
package/routers/mgmt/route.js
CHANGED
|
@@ -128,7 +128,7 @@ router.get('/:id',
|
|
|
128
128
|
);
|
|
129
129
|
|
|
130
130
|
router.post('/',
|
|
131
|
-
(req, res, next) => {
|
|
131
|
+
async (req, res, next) => {
|
|
132
132
|
req.body.Status = AccountAuditStatus.Passed;
|
|
133
133
|
req.body.Saved = true;
|
|
134
134
|
|
|
@@ -144,7 +144,58 @@ router.post('/',
|
|
|
144
144
|
// make sure the provided permission is in the scope of the current user permission!!
|
|
145
145
|
if(req.user.Permission){
|
|
146
146
|
if(req.user.Permission !== '*') {
|
|
147
|
+
// 根据当前账号的权限,检查所传入的权限中的数据权限配置是否合理,
|
|
148
|
+
// 如果合理,将传入的数据权限保存,并合并到最后的权限中
|
|
149
|
+
const permPathList = router.mdl.utils.getPermissionPathList(req.body.Permission);
|
|
150
|
+
const allPerms = await res.app.models.permission.find({
|
|
151
|
+
Path: { $in: permPathList } ,
|
|
152
|
+
Enabled: true
|
|
153
|
+
}).lean();
|
|
154
|
+
|
|
155
|
+
const dsScope = {};
|
|
156
|
+
for (let i = 0; i < allPerms.length; i += 1) {
|
|
157
|
+
const p = allPerms[i].Path;
|
|
158
|
+
const pDot = p.replace(/^\//, '').replace(/\//g, '.');
|
|
159
|
+
const uPerm = Object.nestValue(req.user.Permission, pDot);
|
|
160
|
+
const bPerm = Object.nestValue(req.body.Permission, pDot);
|
|
161
|
+
|
|
162
|
+
if (uPerm && uPerm.Scope && bPerm && bPerm.Scope) {
|
|
163
|
+
// 当前账号此权限中的数据权限定义
|
|
164
|
+
for (let j = 0; j < (allPerms[i].Scope || []).length; j += 1) {
|
|
165
|
+
const sc = allPerms[i].Scope[j];
|
|
166
|
+
|
|
167
|
+
if (!uPerm.Scope[sc.Name] || !bPerm.Scope[sc.Name]) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const dso = res.app.getContainerContent('DataScope').find(ds => ds.Name === sc.Name);
|
|
172
|
+
|
|
173
|
+
if (dso) {
|
|
174
|
+
const dsoOptions = dso.Options || [];
|
|
175
|
+
|
|
176
|
+
const dsOpOfCurrentUser = dsoOptions.find(o => o.Value === uPerm.Scope[sc.Name]);
|
|
177
|
+
const dsOpInBody = dsoOptions.find(o => o.Value === bPerm.Scope[sc.Name]);
|
|
178
|
+
|
|
179
|
+
if (dsOpOfCurrentUser
|
|
180
|
+
&& dsOpInBody
|
|
181
|
+
) {
|
|
182
|
+
if (
|
|
183
|
+
(dsOpOfCurrentUser.Level !== void 0)
|
|
184
|
+
&& (dsOpInBody.Level !== void 0)
|
|
185
|
+
&& (dsOpInBody.Level <= dsOpOfCurrentUser.Level)
|
|
186
|
+
) {
|
|
187
|
+
Object.setValue(dsScope, `${pDot}.Scope.${sc.Name}`, dsOpInBody.Value);
|
|
188
|
+
} else {
|
|
189
|
+
Object.setValue(dsScope, `${pDot}.Scope.${sc.Name}`, dsOpOfCurrentUser.Value);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
147
197
|
req.body.Permission = Object.intersection(req.body.Permission, req.user.Permission);
|
|
198
|
+
Object.assign(req.body.Permission, dsScope);
|
|
148
199
|
}
|
|
149
200
|
} else {
|
|
150
201
|
delete req.body.Permission;
|
|
@@ -215,7 +266,7 @@ router.post('/audit',
|
|
|
215
266
|
);
|
|
216
267
|
|
|
217
268
|
router.put('/',
|
|
218
|
-
(req, res, next) => {
|
|
269
|
+
async (req, res, next) => {
|
|
219
270
|
if (req.body.Permission) {
|
|
220
271
|
if (!clearPermission(req.body.Permission)) {
|
|
221
272
|
req.body.Permission = {};
|
|
@@ -228,7 +279,58 @@ router.put('/',
|
|
|
228
279
|
// make sure the provided permission is in the scope of the current user permission!!
|
|
229
280
|
if(req.user.Permission){
|
|
230
281
|
if(req.user.Permission !== '*') {
|
|
282
|
+
// 根据当前账号的权限,检查所传入的权限中的数据权限配置是否合理,
|
|
283
|
+
// 如果合理,将传入的数据权限保存,并合并到最后的权限中
|
|
284
|
+
const permPathList = router.mdl.utils.getPermissionPathList(req.body.Permission);
|
|
285
|
+
const allPerms = await res.app.models.permission.find({
|
|
286
|
+
Path: { $in: permPathList } ,
|
|
287
|
+
Enabled: true
|
|
288
|
+
}).lean();
|
|
289
|
+
|
|
290
|
+
const dsScope = {};
|
|
291
|
+
for (let i = 0; i < allPerms.length; i += 1) {
|
|
292
|
+
const p = allPerms[i].Path;
|
|
293
|
+
const pDot = p.replace(/^\//, '').replace(/\//g, '.');
|
|
294
|
+
const uPerm = Object.nestValue(req.user.Permission, pDot);
|
|
295
|
+
const bPerm = Object.nestValue(req.body.Permission, pDot);
|
|
296
|
+
|
|
297
|
+
if (uPerm && uPerm.Scope && bPerm && bPerm.Scope) {
|
|
298
|
+
// 当前账号此权限中的数据权限定义
|
|
299
|
+
for (let j = 0; j < (allPerms[i].Scope || []).length; j += 1) {
|
|
300
|
+
const sc = allPerms[i].Scope[j];
|
|
301
|
+
|
|
302
|
+
if (!uPerm.Scope[sc.Name] || !bPerm.Scope[sc.Name]) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const dso = res.app.getContainerContent('DataScope').find(ds => ds.Name === sc.Name);
|
|
307
|
+
|
|
308
|
+
if (dso) {
|
|
309
|
+
const dsoOptions = dso.Options || [];
|
|
310
|
+
|
|
311
|
+
const dsOpOfCurrentUser = dsoOptions.find(o => o.Value === uPerm.Scope[sc.Name]);
|
|
312
|
+
const dsOpInBody = dsoOptions.find(o => o.Value === bPerm.Scope[sc.Name]);
|
|
313
|
+
|
|
314
|
+
if (dsOpOfCurrentUser
|
|
315
|
+
&& dsOpInBody
|
|
316
|
+
) {
|
|
317
|
+
if (
|
|
318
|
+
(dsOpOfCurrentUser.Level !== void 0)
|
|
319
|
+
&& (dsOpInBody.Level !== void 0)
|
|
320
|
+
&& (dsOpInBody.Level <= dsOpOfCurrentUser.Level)
|
|
321
|
+
) {
|
|
322
|
+
Object.setValue(dsScope, `${pDot}.Scope.${sc.Name}`, dsOpInBody.Value);
|
|
323
|
+
} else {
|
|
324
|
+
Object.setValue(dsScope, `${pDot}.Scope.${sc.Name}`, dsOpOfCurrentUser.Value);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
231
332
|
req.body.Permission = Object.intersection(req.body.Permission, req.user.Permission);
|
|
333
|
+
Object.assign(req.body.Permission, dsScope);
|
|
232
334
|
}
|
|
233
335
|
} else {
|
|
234
336
|
delete req.body.Permission;
|
package/routers/perm/route.js
CHANGED
package/sms/index.js
CHANGED
|
@@ -3,6 +3,9 @@ const path = require('path');
|
|
|
3
3
|
const AliyunCore = require('@alicloud/pop-core');
|
|
4
4
|
const nodemailer = require('nodemailer');
|
|
5
5
|
|
|
6
|
+
const submail = require('./platforms/submail');
|
|
7
|
+
const tencent = require('./platforms/tencent');
|
|
8
|
+
|
|
6
9
|
let global;
|
|
7
10
|
|
|
8
11
|
if (fs.existsSync(path.resolve(__dirname, '../../../global.js'))) {
|
|
@@ -66,7 +69,18 @@ const _sms_lib = {
|
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
var codeAndValue = {};
|
|
69
|
-
codeAndValue[k.templateParamName] = v;
|
|
72
|
+
// codeAndValue[k.templateParamName] = v;
|
|
73
|
+
|
|
74
|
+
if (Array.isArray(k.templateParamName)) {
|
|
75
|
+
for (let i = 0; i < k.templateParamName.length; i += 1) {
|
|
76
|
+
const paramName = k.templateParamName[i];
|
|
77
|
+
if (paramName && v && v[paramName]) {
|
|
78
|
+
codeAndValue[paramName] = v[paramName];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
codeAndValue[k.templateParamName] = v;
|
|
83
|
+
}
|
|
70
84
|
|
|
71
85
|
var params = {
|
|
72
86
|
"PhoneNumbers": p,
|
|
@@ -106,7 +120,7 @@ const _sms_lib = {
|
|
|
106
120
|
}
|
|
107
121
|
});
|
|
108
122
|
|
|
109
|
-
const result = await MAIL_TRANS.sendMail({
|
|
123
|
+
const result = await MAIL_TRANS[k.mail].sendMail({
|
|
110
124
|
from: k.from,
|
|
111
125
|
to: p,
|
|
112
126
|
subject: typeof k.title === 'function' ? k.title(v) : k.title,
|
|
@@ -121,6 +135,8 @@ const _sms_lib = {
|
|
|
121
135
|
return result && result.accepted && result.accepted.length >= 1;
|
|
122
136
|
}
|
|
123
137
|
},
|
|
138
|
+
submail,
|
|
139
|
+
tencent,
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
module.exports = (app) => ({
|
|
@@ -137,7 +153,7 @@ module.exports = (app) => ({
|
|
|
137
153
|
|
|
138
154
|
// const keys = (global && global.sms && global.sms[t]) || app.modules.account.config.sms.keys[t] || app.modules.account.config.sms.keys;
|
|
139
155
|
|
|
140
|
-
if (keys.platform) {
|
|
156
|
+
if (keys && keys.platform) {
|
|
141
157
|
// should not send too frequent!
|
|
142
158
|
const lastSentTime = await app.cache.get(`${p}_lastSentTime`);
|
|
143
159
|
if (lastSentTime && (Date.now() - lastSentTime) < (keys.resentGap || (60 * 1000))) {
|
|
@@ -182,7 +198,7 @@ module.exports = (app) => ({
|
|
|
182
198
|
let v = _generateMSG(f);
|
|
183
199
|
return await this.send(p, v, c, t);
|
|
184
200
|
},
|
|
185
|
-
verify: async function (p, v, del) {
|
|
201
|
+
verify: async function (p, v, del = true) {
|
|
186
202
|
const cached = await app.cache.get(p);
|
|
187
203
|
|
|
188
204
|
// clear cache if the code is correct
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const crypto = require("crypto");
|
|
3
|
+
|
|
4
|
+
const client = axios.create({
|
|
5
|
+
baseURL: 'https://api-v4.mysubmail.com',
|
|
6
|
+
timeout: 308 * 1000,
|
|
7
|
+
headers: {
|
|
8
|
+
'Content-Type':'application/json',
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const sign = (appid, appkey, obj) => {
|
|
13
|
+
// 排序obj并转为json字符串
|
|
14
|
+
const bodyStr = Object.keys(obj).sort((a, b) => a > b ? 1 : (a < b ? -1 : 0)).map((k) => `${k}=${obj[k]}`).join('&');
|
|
15
|
+
|
|
16
|
+
// md5
|
|
17
|
+
var md5 = crypto.createHash('md5');
|
|
18
|
+
|
|
19
|
+
return md5.update(`${appid}${appkey}${bodyStr}${appid}${appkey}`).digest('hex');
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// https://www.mysubmail.com/documents/OOVyh
|
|
23
|
+
module.exports = {
|
|
24
|
+
send: async function (k, p, v) {
|
|
25
|
+
if (!k || !k.templateCode || !k.templateParamName) {
|
|
26
|
+
throw new Error('SMS parameters not configured correctly for platform (Submail)');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var codeAndValue = {};
|
|
30
|
+
|
|
31
|
+
if (Array.isArray(k.templateParamName)) {
|
|
32
|
+
for (let i = 0; i < k.templateParamName.length; i += 1) {
|
|
33
|
+
const paramName = k.templateParamName[i];
|
|
34
|
+
if (paramName && v && v[paramName]) {
|
|
35
|
+
codeAndValue[paramName] = v[paramName];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
codeAndValue[k.templateParamName] = v;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const requestBody = {
|
|
43
|
+
appid: k.appid, // 在 SUBMAIL 应用集成中创建的短信应用 ID
|
|
44
|
+
to: p, // 收件人手机号码
|
|
45
|
+
project: k.templateCode, // 模版 ID
|
|
46
|
+
timestamp: Math.floor(Date.now() / 1000), // Timestamp UNIX 时间戳
|
|
47
|
+
sign_type: 'md5', // md5 or sha1 or normal
|
|
48
|
+
sign_version: 2, // signature 加密计算方式(当 sign_version 传 2 时,vars 参数不参与加密计算)
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const signature = sign(k.appid, k.appkey, requestBody);
|
|
52
|
+
|
|
53
|
+
return await client.post('/sms/xsend', {
|
|
54
|
+
...requestBody,
|
|
55
|
+
signature, // 应用密匙或数字签名
|
|
56
|
+
vars: JSON.stringify(codeAndValue), // 使用文本变量动态控制短信中的文本。
|
|
57
|
+
// sms_signature: '', // 自定义短信签名,如果忽略此参数,将使用模板的默认签名作为签名(此参数不参与加密计算)
|
|
58
|
+
}).then(({data}) => {
|
|
59
|
+
if (data.status === 'success') {
|
|
60
|
+
return true;
|
|
61
|
+
} else {
|
|
62
|
+
console.error('SMS send error:', data.msg);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return false;
|
|
66
|
+
}).catch(() => {
|
|
67
|
+
return false;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const tencentcloud = require("tencentcloud-sdk-nodejs-sms");
|
|
2
|
+
|
|
3
|
+
const smsClient = tencentcloud.sms.v20210111.Client;
|
|
4
|
+
|
|
5
|
+
// https://cloud.tencent.com/document/product/382/55981
|
|
6
|
+
module.exports = {
|
|
7
|
+
send: async function (k, p, v) {
|
|
8
|
+
if (!k || !k.SecretId || !k.SecretKey || !k.appid || !k.templateCode || !k.signName || !k.templateParamName) {
|
|
9
|
+
throw new Error('SMS parameters not configured correctly for platform (Tencent)');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var paramValues = [];
|
|
13
|
+
|
|
14
|
+
if (Array.isArray(k.templateParamName)) {
|
|
15
|
+
for (let i = 0; i < k.templateParamName.length; i += 1) {
|
|
16
|
+
const paramName = k.templateParamName[i];
|
|
17
|
+
if (paramName && v && v[paramName]) {
|
|
18
|
+
paramValues.push(v[paramName]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
paramValues.push(v);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const client = new smsClient({
|
|
26
|
+
credential: {
|
|
27
|
+
secretId: k.SecretId,
|
|
28
|
+
secretKey: k.SecretKey,
|
|
29
|
+
},
|
|
30
|
+
region: "ap-beijing",
|
|
31
|
+
// 可选配置实例
|
|
32
|
+
profile: {
|
|
33
|
+
signMethod: "TC3-HMAC-SHA256", // 签名方法
|
|
34
|
+
httpProfile: {
|
|
35
|
+
reqMethod: "POST", // 请求方法
|
|
36
|
+
reqTimeout: 30, // 请求超时时间,默认60s
|
|
37
|
+
headers: {
|
|
38
|
+
Action: 'SendSms',
|
|
39
|
+
Region: 'ap-beijing',
|
|
40
|
+
Version: '2021-01-11',
|
|
41
|
+
Language: 'zh-CN',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return await client
|
|
48
|
+
.SendSms({
|
|
49
|
+
PhoneNumberSet: [p],
|
|
50
|
+
|
|
51
|
+
SmsSdkAppId: k.appid,
|
|
52
|
+
TemplateId: k.templateCode,
|
|
53
|
+
SignName: k.signName,
|
|
54
|
+
|
|
55
|
+
TemplateParamSet: paramValues,
|
|
56
|
+
})
|
|
57
|
+
.then((response) => {
|
|
58
|
+
const data = (response.SendStatusSet || [])[0] || {};
|
|
59
|
+
|
|
60
|
+
if (data.Code === 'Ok') {
|
|
61
|
+
return true;
|
|
62
|
+
} else {
|
|
63
|
+
console.error('SMS send error:', data.Code);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return false;
|
|
67
|
+
})
|
|
68
|
+
.catch((err) => {
|
|
69
|
+
console.log('SMS send error:', err);
|
|
70
|
+
return false;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
package/utils.js
CHANGED
|
@@ -49,7 +49,9 @@ function clearPermission(perm) {
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// add a field if nothing here, otherwise the db will not save it??? should be fixed!!
|
|
53
|
+
// fixed by disabling the minimize option in mongoose, but we still should add this field
|
|
54
|
+
// so we can indicate whether the account has this permission clearly
|
|
53
55
|
if (Object.keys(p).length <= 0) {
|
|
54
56
|
p.has = true;
|
|
55
57
|
}
|