yaml-admin-api 0.0.114 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml-admin-api",
3
- "version": "0.0.114",
3
+ "version": "0.0.116",
4
4
  "license": "MIT",
5
5
  "description": "YAML Admin API package",
6
6
  "type": "commonjs",
@@ -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 email = req.query.email || req.body.email;
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 && email === master_email && password === 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
- memberProjection['password'] = true;
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.password)
108
+ let isPasswordMatch = await comparePassword(password, member[passwordField])
88
109
  if (isPasswordMatch) {
89
- await db.collection(entity).updateOne({ email: email }, { $set: { login_date: new Date() } }, { upsert: false })
90
- delete member.password;
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: '비밀번호가 일치하지 않습니다.' });
@@ -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
- res.json({ r: true, token: req.token, expires: req.expires, member: req.user });
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
- res.json({ r: true, token: req.token, expires: req.expires, member: req.user });
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