free-be-account 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/crypto.js +927 -0
- package/enum.js +7 -0
- package/index.js +1002 -0
- package/package.json +15 -0
- package/routers/index.js +4 -0
- package/routers/label/index.js +4 -0
- package/routers/label/route.js +33 -0
- package/routers/mgmt/index.js +4 -0
- package/routers/mgmt/route.js +279 -0
- package/routers/org/export/index.js +4 -0
- package/routers/org/export/route.js +11 -0
- package/routers/org/index.js +4 -0
- package/routers/org/route.js +67 -0
- package/routers/perm/index.js +4 -0
- package/routers/perm/route.js +94 -0
- package/routers/uc/index.js +4 -0
- package/routers/uc/info/index.js +4 -0
- package/routers/uc/info/route.js +95 -0
- package/routers/uc/phone/index.js +5 -0
- package/routers/uc/phone/route.js +72 -0
- package/routers/uc/pwd/index.js +4 -0
- package/routers/uc/pwd/route.js +41 -0
- package/routers/uc/sub/index.js +4 -0
- package/routers/uc/sub/route.js +158 -0
- package/sms/index.js +134 -0
- package/test/index.js +1 -0
- package/utils.js +209 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const express = require(require('path').resolve('./') + "/node_modules/express");
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
// change phone number
|
|
5
|
+
router.put('/',
|
|
6
|
+
async (req, res, next) => {
|
|
7
|
+
if (!req.body.ophone || !req.body.phone) {
|
|
8
|
+
res.makeError(300, 'Phone number is incorrect!', router.mdl);
|
|
9
|
+
return next('route');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ophone = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.ophone, res.app.modules.account.config.desKey);
|
|
13
|
+
|
|
14
|
+
if (ophone !== req.user.PhoneNumber || ophone.length < 11) {
|
|
15
|
+
res.makeError(300, 'Phone number is incorrect!', router.mdl);
|
|
16
|
+
return next('route');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if (!req.body.phone || req.body.phone.length < 11) {
|
|
21
|
+
res.makeError(301, 'New phone number is incorrect!', router.mdl);
|
|
22
|
+
return next('route');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// update phone number
|
|
26
|
+
req.user.PhoneNumber = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.phone, res.app.modules.account.config.desKey);
|
|
27
|
+
|
|
28
|
+
const oResult = await res.Module('sms').verify(ophone, req.body.ocode);
|
|
29
|
+
if (!oResult) {
|
|
30
|
+
res.makeError(400, 'Verification code for the old phone is incorrect!', router.mdl);
|
|
31
|
+
await res.app.cache.del(ophone);
|
|
32
|
+
await res.app.cache.del(req.user.PhoneNumber);
|
|
33
|
+
return next('route');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const result = await res.Module('sms').verify(req.user.PhoneNumber, req.body.code);
|
|
37
|
+
if (!result) {
|
|
38
|
+
res.makeError(405, 'Verification code for the new phone is incorrect!', router.mdl);
|
|
39
|
+
await res.app.cache.del(ophone);
|
|
40
|
+
await res.app.cache.del(req.user.PhoneNumber);
|
|
41
|
+
return next('route');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// update password
|
|
45
|
+
if (req.body.Password) {
|
|
46
|
+
const password = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.Password, res.app.modules.account.config.desKey);
|
|
47
|
+
if (password) {
|
|
48
|
+
req.user.Password = res.app.modules.account.utils.encryptPwd(password, res.app.modules.account.config.pwdEncryptMethod || 'md5');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const existPhone = await res.app.models.account.countDocuments({ PhoneNumber: req.user.PhoneNumber });
|
|
53
|
+
if (existPhone) {
|
|
54
|
+
res.makeError(402, 'Phone number is already in use!', router.mdl);
|
|
55
|
+
return next('route');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
req.user.Profile = req.user.Profile || {};
|
|
59
|
+
req.user.Profile.Mobile = req.user.PhoneNumber;
|
|
60
|
+
// if user name is the old phone number, set it to the new phone number
|
|
61
|
+
if (req.user.UserName === ophone) {
|
|
62
|
+
req.user.UserName = req.user.PhoneNumber;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// update db
|
|
66
|
+
await req.user.save();
|
|
67
|
+
|
|
68
|
+
return next();
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
module.exports = router;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const express = require(require('path').resolve('./') + "/node_modules/express");
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
// change password
|
|
5
|
+
router.put('/',
|
|
6
|
+
async (req, res, next) => {
|
|
7
|
+
if (!req.body.phone) {
|
|
8
|
+
res.makeError(300, 'Phone number is incorrect!', router.mdl);
|
|
9
|
+
return next('route');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const phone = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.phone, res.app.modules.account.config.desKey);
|
|
13
|
+
|
|
14
|
+
if (phone !== req.user.PhoneNumber || phone.length < 11) {
|
|
15
|
+
res.makeError(301, 'Phone number is incorrect!', router.mdl);
|
|
16
|
+
return next('route');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const result = await res.Module('sms').verify(phone, req.body.code);
|
|
20
|
+
// app.logger.debug(cache.exportJson());
|
|
21
|
+
|
|
22
|
+
if (!result) {
|
|
23
|
+
res.makeError(402, 'Verification code is incorrect!', router.mdl);
|
|
24
|
+
return next('route');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// update password
|
|
28
|
+
if (!req.body.Password) {
|
|
29
|
+
res.makeError(403, 'Please provide the password!', router.mdl);
|
|
30
|
+
return next('route');
|
|
31
|
+
}
|
|
32
|
+
const password = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.Password, res.app.modules.account.config.desKey);
|
|
33
|
+
|
|
34
|
+
req.user.Password = res.app.modules.account.utils.encryptPwd(password, res.app.modules.account.config.pwdEncryptMethod || 'md5');
|
|
35
|
+
await req.user.save();
|
|
36
|
+
|
|
37
|
+
return next();
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
module.exports = router;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const express = require(path.resolve('./') + "/node_modules/express");
|
|
3
|
+
const router = express.Router();
|
|
4
|
+
|
|
5
|
+
const subAccountFilters = [
|
|
6
|
+
{
|
|
7
|
+
Name: 'LastUpdateDate',
|
|
8
|
+
Type: 'DateRange',
|
|
9
|
+
Label: '更新日期',
|
|
10
|
+
Placeholder: '请选择',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
Name: 'Enabled',
|
|
14
|
+
Type: 'Select',
|
|
15
|
+
Label: '激活状态',
|
|
16
|
+
Placeholder: '请选择',
|
|
17
|
+
Options: [
|
|
18
|
+
{
|
|
19
|
+
Label: '已激活',
|
|
20
|
+
Value: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
Label: '未激活',
|
|
24
|
+
Value: false,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
Name: 'Profile.Name',
|
|
30
|
+
Type: 'String',
|
|
31
|
+
Label: '姓名',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
Name: 'Profile.Title',
|
|
35
|
+
Type: 'String',
|
|
36
|
+
Label: '职务',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
Name: 'PhoneNumber',
|
|
40
|
+
Type: 'String',
|
|
41
|
+
Label: '手机号',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
// sub account list
|
|
45
|
+
router.get('/', (req, res, next) => {
|
|
46
|
+
res.locals.filter = {
|
|
47
|
+
Parent: req.user.id
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
res.locals.filter = Object.assign({}, res.app.modules['core-modules'].generateQueryFilter(subAccountFilters, req.query), res.locals.filter);
|
|
51
|
+
|
|
52
|
+
res.locals.fields = [
|
|
53
|
+
'id',
|
|
54
|
+
'LastUpdateDate',
|
|
55
|
+
'Profile',
|
|
56
|
+
'Enabled',
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
return next();
|
|
60
|
+
}, router.FindDocuments('account', false, async (req, res) => {
|
|
61
|
+
// add summary
|
|
62
|
+
res.locals.data.summary = {};
|
|
63
|
+
res.locals.data.summary.enabled = await res.app.models['account'].countDocuments({ Parent: req.user.id, Enabled: true });
|
|
64
|
+
res.locals.data.summary.disabled = await res.app.models['account'].countDocuments({ Parent: req.user.id, Enabled: false });
|
|
65
|
+
|
|
66
|
+
res.locals.data.Filters = subAccountFilters;
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
// create sub accousnt
|
|
70
|
+
router.post('/',
|
|
71
|
+
(req, res, next) => {
|
|
72
|
+
req.body.Parent = req.user.id;
|
|
73
|
+
req.body.Enabled = true;
|
|
74
|
+
// req.body.Permission = req.body.Permission || req.user.Permission;
|
|
75
|
+
// cannot change permission of sub account yet, just assign the same permission with the current account
|
|
76
|
+
req.body.Permission = req.user.Permission;
|
|
77
|
+
res.app.modules.account.utils.clearPermission(req.body.Permission);
|
|
78
|
+
|
|
79
|
+
// also same Org (but should check whether we have Org module??)
|
|
80
|
+
if (req.user.Org) req.body.Org = req.user.Org;
|
|
81
|
+
|
|
82
|
+
// TODO: should not set status here as we don't have this field yet (which was added in passport)
|
|
83
|
+
req.body.Status = '1';
|
|
84
|
+
|
|
85
|
+
// TODO: check permission, should not be bigger than the main account
|
|
86
|
+
|
|
87
|
+
// password
|
|
88
|
+
if (req.body.Password) {
|
|
89
|
+
const password = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.Password, res.app.modules.account.config.desKey);
|
|
90
|
+
req.body.Password = res.app.modules.account.utils.encryptPwd(password, res.app.modules.account.config.pwdEncryptMethod || 'md5');
|
|
91
|
+
}
|
|
92
|
+
return next();
|
|
93
|
+
},
|
|
94
|
+
router.CreateDocument('account')
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// specified sub account list
|
|
98
|
+
router.get('/:id', (req, res, next) => {
|
|
99
|
+
res.locals.filter = {
|
|
100
|
+
Parent: req.user.id,
|
|
101
|
+
id: req.params.id
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
res.locals.fields = [
|
|
105
|
+
'id',
|
|
106
|
+
'Profile',
|
|
107
|
+
'Enabled',
|
|
108
|
+
'PhoneNumber',
|
|
109
|
+
// 'Permission'
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
return next();
|
|
113
|
+
}, router.FindDocuments('account', false, (req, res) => {
|
|
114
|
+
if (res.locals.data && res.locals.data.total) {
|
|
115
|
+
res.locals.data = res.locals.data.docs[0];
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
|
|
119
|
+
// update sub account
|
|
120
|
+
router.put('/:id',
|
|
121
|
+
(req, res, next) => {
|
|
122
|
+
res.locals.filter = {
|
|
123
|
+
Parent: req.user.id,
|
|
124
|
+
id: req.params.id
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
res.locals.fields = [
|
|
128
|
+
'Profile',
|
|
129
|
+
'PhoneNumber',
|
|
130
|
+
'Password',
|
|
131
|
+
'Enabled'
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
if (req.body.Password) {
|
|
135
|
+
const password = res.app.modules.account.utils.crypto.encoder.desDecode(req.body.Password, res.app.modules.account.config.desKey);
|
|
136
|
+
req.body.Password = res.app.modules.account.utils.encryptPwd(password, res.app.modules.account.config.pwdEncryptMethod || 'md5');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// TODO: check permission, should not be bigger than the main account
|
|
140
|
+
|
|
141
|
+
return next();
|
|
142
|
+
},
|
|
143
|
+
router.UpdateDocument('account')
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// delete sub account
|
|
147
|
+
router.delete('/:id',
|
|
148
|
+
(req, res, next) => {
|
|
149
|
+
res.locals.filter = {
|
|
150
|
+
Parent: req.user.id,
|
|
151
|
+
id: req.params.id
|
|
152
|
+
}
|
|
153
|
+
return next();
|
|
154
|
+
},
|
|
155
|
+
router.DeleteDocument('account')
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
module.exports = router;
|
package/sms/index.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const AliyunCore = require('@alicloud/pop-core');
|
|
2
|
+
|
|
3
|
+
function _generateMSG (f = '4n') {
|
|
4
|
+
if (typeof f !== 'string' || f.length < 2) {
|
|
5
|
+
f = '4n';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let mLength = 0,
|
|
9
|
+
mUseNumber = false,
|
|
10
|
+
mUseChar = false;
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < f.length; i += 1) {
|
|
13
|
+
const fi = f[i].toLowerCase();
|
|
14
|
+
|
|
15
|
+
switch (fi) {
|
|
16
|
+
case 'n':
|
|
17
|
+
mUseNumber = true;
|
|
18
|
+
break;
|
|
19
|
+
case 'c':
|
|
20
|
+
mUseChar = true;
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
mLength = mLength || Number(fi) || 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
mLength = mLength || 4;
|
|
28
|
+
if (!mUseNumber && !mUseChar) {
|
|
29
|
+
mUseNumber = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let charList = '';
|
|
33
|
+
if (mUseNumber) charList = charList.concat('1234567890');
|
|
34
|
+
if (mUseChar) charList = charList.concat('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
|
|
35
|
+
|
|
36
|
+
let msgValue = '';
|
|
37
|
+
for (let i = 0; i < mLength; i += 1) {
|
|
38
|
+
msgValue += charList[Math.floor(Math.random() * charList.length)]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return msgValue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const _sms_lib = {
|
|
45
|
+
aliyun: {
|
|
46
|
+
send: async function (k, p, v) {
|
|
47
|
+
if (!k || !k.accessKeyId || !k.secret || !k.signName || !k.templateCode || !k.templateParamName) {
|
|
48
|
+
throw new Error('SMS parameters not configured correctly for platform (Aliyun)');
|
|
49
|
+
}
|
|
50
|
+
var client = new AliyunCore({
|
|
51
|
+
accessKeyId: k.accessKeyId,
|
|
52
|
+
accessKeySecret: k.secret,
|
|
53
|
+
endpoint: 'https://dysmsapi.aliyuncs.com',
|
|
54
|
+
apiVersion: '2017-05-25'
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
var codeAndValue = {};
|
|
58
|
+
codeAndValue[k.templateParamName] = v;
|
|
59
|
+
|
|
60
|
+
var params = {
|
|
61
|
+
"PhoneNumbers": p,
|
|
62
|
+
"SignName": k.signName,
|
|
63
|
+
"TemplateCode": k.templateCode,
|
|
64
|
+
"TemplateParam": JSON.stringify(codeAndValue)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// params[k.templateParamName] = v;
|
|
68
|
+
|
|
69
|
+
var requestOption = {
|
|
70
|
+
method: 'POST'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const result = await client.request('SendSms', params, requestOption);
|
|
74
|
+
|
|
75
|
+
return result && result.Code && result.Code === 'OK';
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
eis: {
|
|
79
|
+
send: async function () {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = (app) => ({
|
|
86
|
+
send: async function (p, value, c = true, t = 'default') {
|
|
87
|
+
const keys = app.config.account.sms[t] || app.config.account.sms;
|
|
88
|
+
if (keys.platform) {
|
|
89
|
+
// if the cached code still there, we should not re-send!
|
|
90
|
+
if (await app.cache.get(p)) {
|
|
91
|
+
throw new Error('Cannot send too frequently!');
|
|
92
|
+
}
|
|
93
|
+
if (_sms_lib[keys.platform]) {
|
|
94
|
+
let sent = true;
|
|
95
|
+
const v = keys.fixedCode || value;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
sent = await _sms_lib[keys.platform].send(keys, p, v);
|
|
99
|
+
} catch (ex) {
|
|
100
|
+
app.logger.error(JSON.stringify(ex));
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (sent) {
|
|
104
|
+
if (c) {
|
|
105
|
+
const cTime = keys.cacheTime || (5 * 60 * 1000)
|
|
106
|
+
await app.cache.put(p, v, cTime);
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
} else {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error(`SMS platform ${keys.platform} is not supported yet!`);
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
throw new Error('SMS platform not configured!');
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @param {String} p Phone number
|
|
122
|
+
* @param {String} f Random pattern, should be like '4nc', 4 means length, n means incude Numbers, c means include Chars.
|
|
123
|
+
* @param {Boolean} c Cache or not
|
|
124
|
+
* @param {String} t template, the key in the sms config
|
|
125
|
+
*/
|
|
126
|
+
sendRandom: async function (p, f, c = true, t = 'default') {
|
|
127
|
+
let v = _generateMSG(f);
|
|
128
|
+
return await this.send(p, v, c, t);
|
|
129
|
+
},
|
|
130
|
+
verify: async function (p, v) {
|
|
131
|
+
const cached = await app.cache.get(p);
|
|
132
|
+
return cached === v;
|
|
133
|
+
}
|
|
134
|
+
})
|
package/test/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// each module should have test script for itself.
|
package/utils.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
const crypto = require('./crypto');
|
|
2
|
+
|
|
3
|
+
const specialNames = [
|
|
4
|
+
'Scope'
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
const EncryptOptions = {
|
|
8
|
+
saltLength: 16,
|
|
9
|
+
sha1Iteration: 1024
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* Translate permission object into path list
|
|
15
|
+
*
|
|
16
|
+
* @param {*} perm
|
|
17
|
+
* @param {*} k
|
|
18
|
+
*/
|
|
19
|
+
function getPermissionPathList(perm, n = '') {
|
|
20
|
+
const ret = [];
|
|
21
|
+
|
|
22
|
+
if (perm && typeof perm === 'object') {
|
|
23
|
+
if (n) ret.push(n);
|
|
24
|
+
|
|
25
|
+
Object.keys(perm).forEach(k => {
|
|
26
|
+
getPermissionPathList(perm[k], k).forEach(p => {
|
|
27
|
+
ret.push(`${n}/${p}`);
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return ret;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function clearPermission(perm) {
|
|
36
|
+
// remove unused fields from permisson object
|
|
37
|
+
// invalid: all values are not object, and all names are in the specified list
|
|
38
|
+
function clearP(p) {
|
|
39
|
+
|
|
40
|
+
if (typeof p !== 'object') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Object.keys(p).forEach(s => {
|
|
45
|
+
if (specialNames.indexOf(s) >= 0) return;
|
|
46
|
+
|
|
47
|
+
if (!clearP(p[s])) {
|
|
48
|
+
delete p[s];
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// TODO: add a field if nothing here, otherwise the db will not save it??? should be fixed!!
|
|
53
|
+
if (Object.keys(p).length <= 0) {
|
|
54
|
+
p.has = true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return clearP(perm);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function verifyPassword(pwd, storedPwd, method = 'md5') {
|
|
64
|
+
let verified = false;
|
|
65
|
+
let methods = [];
|
|
66
|
+
|
|
67
|
+
if (typeof method === 'string') {
|
|
68
|
+
methods.push(method);
|
|
69
|
+
} else if (Array.isArray(method)) {
|
|
70
|
+
methods = method;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < methods.length; i += 1) {
|
|
74
|
+
const m = methods[i];
|
|
75
|
+
switch (m) {
|
|
76
|
+
case 'md5':
|
|
77
|
+
verified = verified || (crypto.MD5(pwd) === storedPwd);
|
|
78
|
+
break;
|
|
79
|
+
case 'sha1':
|
|
80
|
+
verified = verified || (crypto.sha1(pwd, storedPwd.substr(0, EncryptOptions.saltLength), EncryptOptions.sha1Iteration).toString() === storedPwd.substr(EncryptOptions.saltLength));
|
|
81
|
+
break;
|
|
82
|
+
case 'bcrypt':
|
|
83
|
+
verified = verified || crypto.bcryptVerify(pwd, storedPwd);
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
verified = verified || (pwd === storedPwd);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (verified) return verified;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return verified;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getClearPwd(pwd, key){
|
|
96
|
+
if(!pwd) return undefined;
|
|
97
|
+
|
|
98
|
+
return crypto.encoder.desDecode(pwd.substr(EncryptOptions.saltLength), key);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function encryptPwd(pwd, method) {
|
|
102
|
+
let theMethod = [];
|
|
103
|
+
|
|
104
|
+
if (typeof method === 'string') {
|
|
105
|
+
theMethod = method;
|
|
106
|
+
} else if (Array.isArray(method)) {
|
|
107
|
+
theMethod = method[0];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let salt;
|
|
111
|
+
if (theMethod === 'sha1') {
|
|
112
|
+
salt = crypto.generateSalt(EncryptOptions.saltLength / 2);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
switch (theMethod) {
|
|
116
|
+
case 'md5':
|
|
117
|
+
return crypto.MD5(pwd);
|
|
118
|
+
case 'sha1':
|
|
119
|
+
return `${salt}${crypto.sha1(pwd, salt.toString(), EncryptOptions.sha1Iteration)}`;
|
|
120
|
+
case 'bcrypt':
|
|
121
|
+
return crypto.bcrypt(pwd);
|
|
122
|
+
default:
|
|
123
|
+
throw 'Unknown password encrypt method!'
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function saveServiceList (app, clean=false) {
|
|
128
|
+
// add app.serviceList into db if not yet
|
|
129
|
+
const checkService = async (perm, parent, pt) => {
|
|
130
|
+
if (!perm || typeof perm !== 'object') return;
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < Object.keys(perm).length; i += 1) {
|
|
133
|
+
const p = Object.keys(perm)[i];
|
|
134
|
+
|
|
135
|
+
// TODO: notify user if they are creating permission with these names
|
|
136
|
+
if (['title', 'description', 'scope', 'label'].indexOf(p.toLowerCase()) >= 0) continue;
|
|
137
|
+
|
|
138
|
+
let newCreated;
|
|
139
|
+
const existCount = await app.models['permission'].countDocuments({ Name: p, Path: `${pt}/${p}` });
|
|
140
|
+
if (existCount <= 0) {
|
|
141
|
+
const newDoc = {
|
|
142
|
+
Name: p,
|
|
143
|
+
Title: perm[p].title,
|
|
144
|
+
Description: typeof perm[p].description === 'string' ? perm[p].description : JSON.stringify(perm[p].description),
|
|
145
|
+
Index: i + 1,
|
|
146
|
+
Path: `${pt}/${p}`
|
|
147
|
+
};
|
|
148
|
+
if (parent) newDoc.Parent = parent;
|
|
149
|
+
|
|
150
|
+
newCreated = await app.models.permission.create(newDoc);
|
|
151
|
+
} else {
|
|
152
|
+
newCreated = (await app.models['permission'].findOne({ Name: p, Path: `${pt}/${p}`}));
|
|
153
|
+
|
|
154
|
+
// update
|
|
155
|
+
newCreated.Title = perm[p].title;
|
|
156
|
+
newCreated.Description = typeof perm[p].description === 'string' ? perm[p].description : JSON.stringify(perm[p].description);
|
|
157
|
+
if(parent) newCreated.Parent = parent;
|
|
158
|
+
newCreated.Index = i + 1;
|
|
159
|
+
await newCreated.save();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (newCreated) {
|
|
163
|
+
await checkService(perm[p], newCreated.id, `${pt}/${p}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// clear all built-in permissions first
|
|
169
|
+
if(clean){
|
|
170
|
+
const userCreatedList = await app.models.permission.find({ BuiltIn: false });
|
|
171
|
+
if(userCreatedList && userCreatedList.length > 0){
|
|
172
|
+
const uclIds = [];
|
|
173
|
+
const addParentId = async (p) => {
|
|
174
|
+
if(!p) return;
|
|
175
|
+
|
|
176
|
+
const parent = await app.models.permission.findOne({id: p});
|
|
177
|
+
|
|
178
|
+
if(parent && uclIds.indexOf(parent.id) < 0){
|
|
179
|
+
uclIds.push(parent.id);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
await addParentId(parent.Parent);
|
|
183
|
+
}
|
|
184
|
+
for (let i = 0; i < userCreatedList.length; i += 1) {
|
|
185
|
+
const ucli = userCreatedList[i];
|
|
186
|
+
|
|
187
|
+
uclIds.push(ucli.id);
|
|
188
|
+
|
|
189
|
+
await addParentId(ucli.Parent);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// remove all built-in
|
|
193
|
+
await app.models.permission.remove({id: {$nin: uclIds}});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const serviceList = app.ctx.serviceList();
|
|
198
|
+
await checkService(serviceList, undefined, '');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
module.exports = {
|
|
202
|
+
clearPermission,
|
|
203
|
+
getPermissionPathList,
|
|
204
|
+
verifyPassword,
|
|
205
|
+
encryptPwd,
|
|
206
|
+
getClearPwd,
|
|
207
|
+
crypto,
|
|
208
|
+
saveServiceList,
|
|
209
|
+
}
|