yaml-admin-api 0.0.3

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 ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "yaml-admin-api",
3
+ "version": "0.0.3",
4
+ "description": "YAML Admin API package",
5
+ "type": "commonjs",
6
+ "main": "src/index.js",
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "license": "MIT",
11
+ "dependencies": {
12
+ "bcryptjs": "^3.0.2",
13
+ "jsonwebtoken": "^9.0.2",
14
+ "mongodb": "^6.18.0",
15
+ "request": "^2.88.2",
16
+ "yaml": "^2.8.1"
17
+ }
18
+ }
@@ -0,0 +1,118 @@
1
+ const isAuthenticated = (jwt_secret) => {
2
+ return async (req, res, next) => {
3
+ const token = req.headers['x-access-token'] || req.query.token || req.cookies.token;
4
+ if (token == null)
5
+ res.json({ r: false, err: { code: 666 }, msg: '로그인 필요' });
6
+ else {
7
+ jwt.verify(token, jwt_secret, (err, decoded) => {
8
+ if (err) {
9
+ res.json({ r: false, err: { code: 666 }, msg: '로그인 필요' });
10
+ return;
11
+ }
12
+ req.user = decoded;
13
+ delete req.user.password;
14
+ next();
15
+ })
16
+ }
17
+ }
18
+ }
19
+
20
+ const generateList = async ({app, db, name, entity, jwt_secret}) => {
21
+ //list
22
+ app.get(`/${name}`, isAuthenticated(jwt_secret), async function (req, res) {
23
+ var s = {};
24
+ var _sort = req.query._sort;
25
+ var _order = req.query._order;
26
+ if (_sort != null)
27
+ s[_sort] = (_order == 'ASC' ? 1 : -1);
28
+
29
+ var _end = req.query._end;
30
+ var _start = req.query._start;
31
+ var l = _end - _start;
32
+
33
+ //검색 파라미터
34
+ var f = {};
35
+ var id = req.query.id;
36
+ if (id) {
37
+ if (Array.isArray(id))
38
+ f['id'] = { $in: id.map(m => parseInt(m)) };
39
+ else
40
+ f['id'] = parseInt(id);
41
+ }
42
+
43
+ // ${
44
+ // entity.property.filter(f=>f.search && f.type != 'divider').map(m=>{
45
+ // if(m.type == 'bool') {
46
+ // return `
47
+ // if (req.query.${m.name})
48
+ // f['${m.name}'] = req.query.${m.name} == 'true'
49
+ // `
50
+ // } else if(m.type == 'text') {
51
+ // return `
52
+ // if (req.query.${m.name})
53
+ // f['${m.name}'] = { $regex: ".*" + req.query.${m.name} + ".*" }
54
+ // `
55
+ // } else if(m.type == 'reference') {
56
+ // //reference의 키는 integer인지 string인지 모른다. 그리고 member_no같이 string으로 취급되어야할 integer도 있다
57
+ // return `
58
+ // if (req.query.${m.name})
59
+ // f['${m.name}'] = isNaN(Number(req.query.${m.name}))|| parseInt(req.query.${m.name}) > 1569340492095?req.query.${m.name}:parseInt(req.query.${m.name})
60
+ // `
61
+ // } else if(m.type == 'date') {
62
+ // return `
63
+ // if (req.query.date) {
64
+ // if(req.query.date.replace(/-/g, '').length == 8) {
65
+ // //해당 날짜의 시작Date와 끝Date로 검색
66
+ // f['date'] = {
67
+ // $gte: moment(req.query.date).startOf('day').toDate(),
68
+ // $lte: moment(req.query.date).endOf('day').toDate()
69
+ // }
70
+ // }
71
+ // }
72
+ // `
73
+ // } else {
74
+ // return `
75
+ // if (req.query.${m.name})
76
+ // f['${m.name}'] = req.query.${m.name}
77
+ // `
78
+ // }
79
+
80
+ // }).join('\n')
81
+ // }
82
+
83
+ var name = req.query.name;
84
+ if (name == null && req.query.q)
85
+ name = req.query.q;
86
+ if (name != null)
87
+ f['name'] = { $regex: ".*" + name + ".*" };
88
+ f.remove = { $ne: true }
89
+
90
+ //Custom f list Start
91
+
92
+ //Custom f list End
93
+
94
+ var count = await db.collection('${name}').find(f).project({ _id: false }).sort(s).count();
95
+ let list = await db.collection('${name}').find(f).project({ _id: false }).sort(s).skip(parseInt(_start)).limit(l).toArray()
96
+ console.log('entity', entity)
97
+ list.map(m => {
98
+ m.id = entity.key
99
+ })
100
+ //Custom list Start
101
+
102
+ //Custom list End
103
+ await addInfo(db, list)
104
+ res.header('X-Total-Count', count);
105
+ res.json(list);
106
+ });
107
+ }
108
+
109
+ const generateEntityApi = async ({app, db, name, entity, jwt_secret}) => {
110
+ const { fields } = entity;
111
+ console.log('generateEntityApi', name)
112
+
113
+ await generateList({app, db, name, entity, jwt_secret})
114
+ }
115
+
116
+ module.exports = {
117
+ generateEntityApi
118
+ }
@@ -0,0 +1,10 @@
1
+ const member = require('../member/member.js');
2
+
3
+ const generateLoginApi = async(app, db, yml) => {
4
+ console.log('generateLoginApi', yml.login["jwt-secret"])
5
+ await member(app, db, yml)
6
+ }
7
+
8
+ module.exports = {
9
+ generateLoginApi
10
+ }
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ const registerRoutes = require('./yml-admin-api.js');
2
+
3
+ module.exports = { registerRoutes };
@@ -0,0 +1,86 @@
1
+ const bcrypt = require('bcryptjs');
2
+ const jwt = require('jsonwebtoken');
3
+
4
+ const withConfig = (config) => {
5
+ const { db, jwt_secret } = config;
6
+
7
+ const comparePassword = function (plainPass, hashword, callback) {
8
+ bcrypt.compare(plainPass, hashword, function (err, isPasswordMatch) {
9
+ return err == null ?
10
+ callback(null, isPasswordMatch) :
11
+ callback(err);
12
+ });
13
+ };
14
+
15
+ const authenticateSuccess = function (req, res, user, next) {
16
+ jwt.sign(
17
+ user,
18
+ jwt_secret,
19
+ {
20
+ expiresIn: '1000d',
21
+ subject: 'userInfo'
22
+ }, (err, token) => {
23
+ if (err) res.json({ r: false, msg: '알 수 없는 이유로 토큰 생성에 실패하였습니다.' });
24
+
25
+ req.token = token;
26
+ delete user.password;
27
+ req.user = user;
28
+ next();
29
+ }
30
+ );
31
+ };
32
+
33
+ const isAuthenticated = function (req, res, next) {
34
+ const token = req.headers['x-access-token'] || req.query.token || req.cookies.token;
35
+
36
+ if (token == null)
37
+ res.json({ r: false, err: { code: 666 }, msg: '로그인 필요' });
38
+ else
39
+ jwt.verify(token, jwt_secret, (err, decoded) => {
40
+ if (err) {
41
+ res.json({ r: false, err: { code: 666 }, msg: '로그인 필요' });
42
+ return;
43
+ }
44
+ req.user = decoded;
45
+ next();
46
+ })
47
+ };
48
+
49
+ const authenticate = async (req, res, next) => {
50
+ const email = req.query.email || req.body.email;
51
+ const password = req.query.pass || req.body.pass;
52
+ const type = req.query.type || req.body.type || "email";
53
+ if (email === 'admin' && password === '5756') {
54
+ authenticateSuccess(req, res,
55
+ { id: '1111111', email: 'admin', name: 'admin', type: 'email' },
56
+ next);
57
+ }
58
+ else {
59
+ var memberProjection = { projection: { _id: false, name: true, email: true, password: true, super: true, id: true } };
60
+ if (type === 'email') {
61
+ memberProjection['password'] = true;
62
+ let member = await db.collection('admin').findOne({ email: email }, memberProjection)
63
+ if (member != null) {
64
+ comparePassword(password, member.password, async function (err, isPasswordMatch) {
65
+ if (isPasswordMatch) {
66
+ authenticateSuccess(req, res, member, next);
67
+ await db.collection('admin').updateOne({ email: email }, { $set: { login_date: new Date() } }, { upsert: false })
68
+ } else
69
+ res.json({ r: false, msg: '비밀번호가 일치하지 않습니다.' });
70
+ });
71
+ }
72
+ else
73
+ res.json({ r: false, msg: '존재하지 않는 사용자입니다.' });
74
+ }
75
+ }
76
+ };
77
+
78
+ return {
79
+ isAuthenticated,
80
+ authenticate,
81
+ }
82
+ }
83
+
84
+ module.exports = {
85
+ withConfig,
86
+ }
@@ -0,0 +1,32 @@
1
+ const {withConfig} = require('../login/auth.js');
2
+
3
+ module.exports = async function (app, db, yml, delegate) {
4
+ const auth = withConfig({ db, jwt_secret: yml.login["jwt-secret"] });
5
+
6
+ app.get('/member/login',
7
+ auth.authenticate,
8
+ function (req, res) {
9
+ res.json({ r: true, token: req.token, member: req.user });
10
+ }
11
+ );
12
+
13
+ app.get('/member/islogin',
14
+ auth.isAuthenticated,
15
+ async function (req, res) {
16
+ res.json({ r: true, member: req.user });
17
+ }
18
+ );
19
+
20
+ app.post('/member/login',
21
+ auth.authenticate,
22
+ function (req, res) {
23
+ res.json({ r: true, token: req.token, member: req.user });
24
+ }
25
+ );
26
+
27
+ app.get('/member/logout', async (req, res) => {
28
+ req.logout();
29
+ res.json({ r: true });
30
+ });
31
+
32
+ };
@@ -0,0 +1,57 @@
1
+ const { MongoClient } = require('mongodb');
2
+ const fs = require('fs').promises;
3
+ const yaml = require('yaml');
4
+ const { generateEntityApi } = require('./crud/api-generator');
5
+ const { generateLoginApi } = require('./crud/login-api-generator');
6
+
7
+ async function registerRoutes(app, options = {}) {
8
+ const { yamlPath, yamlString } = options;
9
+ let yml;
10
+ if(yamlPath) {
11
+ yml = await readYml(yamlPath);
12
+ } else if(yamlString) {
13
+ yml = yaml.parse(yamlString);
14
+ } else {
15
+ let yamlString = await fs.readFile('./admin.yml', 'utf8');
16
+ if(!yamlString) {
17
+ throw new Error('admin.yml is not found. yamlPath or yamlString is required.')
18
+ }
19
+ yamlString = yamlString.replace('${JWT_SECRET}', process.env.JWT_SECRET);
20
+ yamlString = yamlString.replace('${MONGODB_URL}', process.env.MONGODB_URL);
21
+ yml = yaml.parse(yamlString);
22
+ }
23
+
24
+ const {database, entity} = yml;
25
+ let db = null;
26
+ if(database) {
27
+ const {mongodb} = database;
28
+ if(mongodb) {
29
+ const {uri} = mongodb;
30
+ db = await MongoClient.connect(uri, {}).then(client => client.db())
31
+ console.log('db connected')
32
+ }
33
+ }
34
+ const jwt_secret = yml.login["jwt-secret"]
35
+ app.set('jwt-secret', jwt_secret);
36
+
37
+ await generateLoginApi(app, db, yml)
38
+ entity && Object.keys(entity).forEach(async (entityName) => {
39
+ await generateEntityApi({
40
+ app, db,
41
+ name:entityName,
42
+ entity:entity[entityName],
43
+ jwt_secret
44
+ })
45
+ })
46
+ }
47
+
48
+ async function readYml(path) {
49
+ let yml = await fs.readFile(path, 'utf8');
50
+ yml = yml.replace('${JWT_SECRET}', process.env.JWT_SECRET);
51
+ yml = yml.replace('${MONGODB_URL}', process.env.MONGODB_URL);
52
+
53
+ return yaml.parse(yml);
54
+
55
+ }
56
+
57
+ module.exports = registerRoutes;