yaml-admin-api 0.0.115 → 0.0.116
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/package.json +1 -1
- package/src/crud/entity-api-generator.js +10 -3
- package/src/login/auth.js +35 -10
- package/src/member/member.js +7 -3
package/package.json
CHANGED
|
@@ -16,6 +16,13 @@ const asyncErrorHandler = (fn) => (req, res, next) => {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
const checkAuthority = (action) => (req, res, next) => {
|
|
20
|
+
const authority = req.user?.authority;
|
|
21
|
+
if (authority && authority[action] === false)
|
|
22
|
+
return res.status(403).json({ r: false, msg: '권한이 없습니다.' });
|
|
23
|
+
next();
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options }) => {
|
|
20
27
|
|
|
21
28
|
// entity 속성이 있으면 해당 값을 실제 collection 이름으로 사용
|
|
@@ -402,7 +409,7 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
402
409
|
};
|
|
403
410
|
|
|
404
411
|
//create
|
|
405
|
-
app.post(`${api_prefix}/${entity_name}`, auth.isAuthenticated, asyncErrorHandler(async (req, res) => {
|
|
412
|
+
app.post(`${api_prefix}/${entity_name}`, auth.isAuthenticated, checkAuthority('create'), asyncErrorHandler(async (req, res) => {
|
|
406
413
|
|
|
407
414
|
await recalcurateAutoGenerateIndex(db, entity_name)
|
|
408
415
|
|
|
@@ -455,7 +462,7 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
455
462
|
|
|
456
463
|
|
|
457
464
|
//edit
|
|
458
|
-
app.put(`${api_prefix}/${entity_name}/:id`, auth.isAuthenticated, asyncErrorHandler(async (req, res) => {
|
|
465
|
+
app.put(`${api_prefix}/${entity_name}/:id`, auth.isAuthenticated, checkAuthority('edit'), asyncErrorHandler(async (req, res) => {
|
|
459
466
|
let entityId = parseKey(req.params.id)
|
|
460
467
|
|
|
461
468
|
const entity = await constructEntity(req, entityId);
|
|
@@ -509,7 +516,7 @@ const generateCrud = async ({ app, db, entity_name, yml_entity, yml, options })
|
|
|
509
516
|
}));
|
|
510
517
|
|
|
511
518
|
//delete
|
|
512
|
-
app.delete(`${api_prefix}/${entity_name}/:id`, auth.isAuthenticated, asyncErrorHandler(async (req, res) =>{
|
|
519
|
+
app.delete(`${api_prefix}/${entity_name}/:id`, auth.isAuthenticated, checkAuthority('delete'), asyncErrorHandler(async (req, res) =>{
|
|
513
520
|
|
|
514
521
|
let f = {}
|
|
515
522
|
f[key_field.name] = parseKey(req.params.id)
|
package/src/login/auth.js
CHANGED
|
@@ -2,8 +2,27 @@ const bcrypt = require('bcryptjs');
|
|
|
2
2
|
const jwt = require('jsonwebtoken');
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
|
|
5
|
+
const evaluateCondition = (condition, data) => {
|
|
6
|
+
if (!condition) return true;
|
|
7
|
+
const eqMatch = condition.match(/^(\w+)==['"]?([^'"]+)['"]?$/);
|
|
8
|
+
const neqMatch = condition.match(/^(\w+)!=\s*['"]?([^'"]+)['"]?$/);
|
|
9
|
+
if (eqMatch) return String(data[eqMatch[1]]) === eqMatch[2];
|
|
10
|
+
if (neqMatch) return String(data[neqMatch[1]]) !== neqMatch[2];
|
|
11
|
+
return false;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const resolveAuthority = (member, authorityConfig) => {
|
|
15
|
+
if (!authorityConfig) return null;
|
|
16
|
+
for (const rule of Object.values(authorityConfig)) {
|
|
17
|
+
if (evaluateCondition(rule.if, member)) {
|
|
18
|
+
return rule.default || null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
|
|
5
24
|
const withConfig = (config) => {
|
|
6
|
-
const { db, jwt_secret, passwordEncoding, master_email, master_password, expires } = config;
|
|
25
|
+
const { db, jwt_secret, passwordEncoding, master_email, master_password, expires, authority } = config;
|
|
7
26
|
const comparePassword = async (plainPass, hashword) => {
|
|
8
27
|
if(passwordEncoding === 'bcrypt') {
|
|
9
28
|
let isPasswordMatch = await bcrypt.compare(plainPass, hashword)
|
|
@@ -68,26 +87,32 @@ const withConfig = (config) => {
|
|
|
68
87
|
})
|
|
69
88
|
};
|
|
70
89
|
|
|
90
|
+
const idPasswordConfig = config['id-password'] || {};
|
|
91
|
+
const idField = idPasswordConfig['id-field'];
|
|
92
|
+
const passwordField = idPasswordConfig['password-field'];
|
|
93
|
+
const loginEntity = idPasswordConfig['entity'];
|
|
94
|
+
|
|
71
95
|
const authenticate = async (req, res, next) => {
|
|
72
|
-
const
|
|
96
|
+
const idValue = req.query.email || req.body.email;
|
|
73
97
|
const password = req.query.pass || req.body.pass;
|
|
74
98
|
const type = req.query.type || req.body.type || "email";
|
|
75
|
-
if (master_email && master_password &&
|
|
99
|
+
if (master_email && master_password && idValue === master_email && password === master_password) {
|
|
76
100
|
authenticateSuccess(req, res,
|
|
77
101
|
{ id: '1111111', email: 'master', name: 'master', type: 'email' },
|
|
78
102
|
next);
|
|
79
103
|
}
|
|
80
104
|
else {
|
|
81
|
-
const memberProjection = { projection: { _id: false } };
|
|
82
105
|
if (type === 'email') {
|
|
83
|
-
|
|
84
|
-
let entity = 'admin';
|
|
85
|
-
let member = await db.collection(entity).findOne({ email: email }, memberProjection)
|
|
106
|
+
let member = await db.collection(loginEntity).findOne({ [idField]: idValue }, { projection: { _id: false } });
|
|
86
107
|
if (member != null) {
|
|
87
|
-
let isPasswordMatch = await comparePassword(password, member
|
|
108
|
+
let isPasswordMatch = await comparePassword(password, member[passwordField])
|
|
88
109
|
if (isPasswordMatch) {
|
|
89
|
-
await db.collection(
|
|
90
|
-
delete member
|
|
110
|
+
await db.collection(loginEntity).updateOne({ [idField]: idValue }, { $set: { login_date: new Date() } }, { upsert: false })
|
|
111
|
+
delete member[passwordField];
|
|
112
|
+
delete member._id;
|
|
113
|
+
const resolvedAuthority = resolveAuthority(member, authority);
|
|
114
|
+
if (resolvedAuthority) member.authority = resolvedAuthority;
|
|
115
|
+
console.log('member', member)
|
|
91
116
|
authenticateSuccess(req, res, member, next);
|
|
92
117
|
} else
|
|
93
118
|
res.json({ r: false, msg: '비밀번호가 일치하지 않습니다.' });
|
package/src/member/member.js
CHANGED
|
@@ -5,13 +5,16 @@ module.exports = async function (app, db, yml, api_prefix) {
|
|
|
5
5
|
passwordEncoding: yml.login["password-encoding"],
|
|
6
6
|
master_email: yml.login["master-email"],
|
|
7
7
|
master_password: yml.login["master-password"],
|
|
8
|
-
expires: yml.login["expires"]
|
|
8
|
+
expires: yml.login["expires"],
|
|
9
|
+
authority: yml.login["authority"],
|
|
10
|
+
'id-password': yml.login["id-password"]
|
|
9
11
|
});
|
|
10
12
|
|
|
11
13
|
app.get(api_prefix + '/member/login',
|
|
12
14
|
auth.authenticate,
|
|
13
15
|
function (req, res) {
|
|
14
|
-
|
|
16
|
+
const { authority, ...member } = req.user;
|
|
17
|
+
res.json({ r: true, token: req.token, expires: req.expires, authority, member });
|
|
15
18
|
}
|
|
16
19
|
);
|
|
17
20
|
|
|
@@ -25,7 +28,8 @@ module.exports = async function (app, db, yml, api_prefix) {
|
|
|
25
28
|
app.post(api_prefix + '/member/login',
|
|
26
29
|
auth.authenticate,
|
|
27
30
|
function (req, res) {
|
|
28
|
-
|
|
31
|
+
const { authority, ...member } = req.user;
|
|
32
|
+
res.json({ r: true, token: req.token, expires: req.expires, authority, member });
|
|
29
33
|
}
|
|
30
34
|
);
|
|
31
35
|
|