add javascript standard check

This commit is contained in:
Jay 2017-06-06 20:40:51 +08:00
parent 298bf45585
commit b390643a70
13 changed files with 1674 additions and 597 deletions

View File

@ -1,57 +1,56 @@
const koa = require('koa'); const Koa = require('koa')
const path = require('path'); const path = require('path')
const fs = require('fs'); const mongoose = require('mongoose')
const mongoose = require('mongoose');
// Load config // Load config
const config = require('./config.json'); const config = require('./config.json')
// custom modules // custom modules
const mysql = require('./libs/mysql_pool'); const mysql = require('./libs/mysql_pool')
const so = require('./libs/storeObject'); // const so = require('./libs/storeObject')
const mem = require('./libs/memcache_lib'); const mem = require('./libs/memcache_lib')
const sendmail = require('./libs/sendmail'); // const sendmail = require('./libs/sendmail')
// init memcached connection // init memcached connection
mem.host = 'dyn.trj.tw'; mem.host = 'dyn.trj.tw'
mem.port = 24002; mem.port = 24002
mem.connect(); mem.connect()
// init mysql connection pool // init mysql connection pool
mysql.database = config.db.mysql.dbname; mysql.database = config.db.mysql.dbname
mysql.host = config.db.mysql.host; mysql.host = config.db.mysql.host
mysql.user = config.db.mysql.user; mysql.user = config.db.mysql.user
mysql.password = config.db.mysql.pass; mysql.password = config.db.mysql.pass
mysql.port = config.db.mysql.port; mysql.port = config.db.mysql.port
mysql.createPool(); mysql.createPool()
// init mongodb connection // init mongodb connection
let mongoAuth = `${config.db.mongo.user.length > 0 && config.db.mongo.pass.length > 0 ? `${config.db.mongo.user}:${config.db.mongo.pass}@` : ''}`; let mongoAuth = `${config.db.mongo.user.length > 0 && config.db.mongo.pass.length > 0 ? `${config.db.mongo.user}:${config.db.mongo.pass}@` : ''}`
let mongoUrl = `mongodb://${mongoAuth}${config.db.mongo.host}:${config.db.mongo.port}/${config.db.mongo.dbname}${mongoAuth.length > 0 ? '?authSource=admin': ''}`; let mongoUrl = `mongodb://${mongoAuth}${config.db.mongo.host}:${config.db.mongo.port}/${config.db.mongo.dbname}${mongoAuth.length > 0 ? '?authSource=admin' : ''}`
mongoose.connect(mongoUrl); mongoose.connect(mongoUrl)
// Koa Middleware // Koa Middleware
const session = require('koa-session'); const session = require('koa-session')
const Router = require('koa-router'); const Router = require('koa-router')
const koaBody = require('koa-body'); // const koaBody = require('koa-body')
const koaStatic = require('koa-static'); const koaStatic = require('koa-static')
const cors = require('kcors'); const cors = require('kcors')
const logger = require('koa-morgan'); const logger = require('koa-morgan')
// Koa Main Application // Koa Main Application
const app = new koa(); const app = new Koa()
const server = app.listen(config.port, () => { const server = app.listen(config.port, () => {
console.log(`Server start on port ${server.address().port}`); console.log(`Server start on port ${server.address().port}`)
}); })
// Root Router // Root Router
const router = new Router(); const router = new Router()
// set app keys // set app keys
app.keys = ['44b4fa5cb8a394294361']; app.keys = ['44b4fa5cb8a394294361']
// enable logger // enable logger
app.use(logger('dev')); app.use(logger('dev'))
// enable body parser // enable body parser
// app.use(koaBody({ // app.use(koaBody({
// multipart: true, // multipart: true,
@ -59,27 +58,27 @@ app.use(logger('dev'));
// maxFieldSize: 10 * 1024 * 1024 // maxFieldSize: 10 * 1024 * 1024
// })); // }));
// enable cors // enable cors
app.use(cors()); app.use(cors())
// enable session // enable session
app.use(session({ app.use(session({
key: 'koa:sess', key: 'koa:sess',
maxAge: 86400000, maxAge: 86400000,
overwrite: true, overwrite: true,
httpOnly: true, httpOnly: true,
signed: true signed: true
}, app)); }, app))
// enable static file // enable static file
app.use(koaStatic(path.resolve(__dirname, 'public'))); app.use(koaStatic(path.resolve(__dirname, 'public')))
// enable router // enable router
app.use(router.routes()); app.use(router.routes())
app.use(router.allowedMethods()); app.use(router.allowedMethods())
// load other route // load other route
const api_route = require('./route/api'); const apiRoute = require('./route/api')
// set other route // set other route
router.use("/api", api_route.routes()); router.use('/api', apiRoute.routes())
router.get('/', async(c, n) => { router.get('/', async(c, n) => {
c.body = 'Get root'; c.body = 'Get root'
}); })

View File

@ -1,48 +1,48 @@
var crypto = require('crypto'); var crypto = require('crypto')
/** /**
* *
* @param {number} len * @param {number} len
*/ */
var random = (len = 32) => { var random = (len = 32) => {
var buf = crypto.randomBytes(len); var buf = crypto.randomBytes(len)
return buf.toString("hex"); return buf.toString('hex')
} }
/** /**
* *
* @param {string} str * @param {string} str
*/ */
var sha256 = (str) => { var sha256 = (str) => {
return crypto.createHash("sha256").update(str).digest('base64'); return crypto.createHash('sha256').update(str).digest('base64')
} }
/** /**
* *
* @param {string} str * @param {string} str
*/ */
var genPassHash = (str) => { var genPassHash = (str) => {
var hash = random(16); var hash = random(16)
var pass = sha256(str + hash); var pass = sha256(str + hash)
return `$${hash}$${pass}`; return `$${hash}$${pass}`
} }
/** /**
* *
* @param {string} plain * @param {string} plain
* @param {string} hash * @param {string} hash
*/ */
var comparePass = (plain, hash) => { var comparePass = (plain, hash) => {
var match = hash.match(/^\$(.+?)\$(.+)$/); var match = hash.match(/^\$(.+?)\$(.+)$/)
if (match == null || match.length < 3 || !match[1] || !match[2]) return false; if (match == null || match.length < 3 || !match[1] || !match[2]) return false
var pass = sha256(plain + match[1]); var pass = sha256(plain + match[1])
if (pass == match[2]) return true; if (pass === match[2]) return true
return false; return false
} }
module.exports = { module.exports = {
random, random,
sha256, sha256,
genPassHash, genPassHash,
comparePass comparePass
} }

View File

@ -1,48 +1,48 @@
const Memcached = require('memcached'); const Memcached = require('memcached')
class memcachedLib { class MemcachedLib {
constructor() { constructor () {
this._host = '' this._host = ''
this._port = '' this._port = ''
this._expire = 86400 this._expire = 86400
this._conn = null; this._conn = null
} }
connect() { connect () {
this._conn = new Memcached(`${this._host}:${this._port}`) this._conn = new Memcached(`${this._host}:${this._port}`)
} }
/** /**
* set object to memcached * set object to memcached
* @param {string} key * @param {string} key
* @param {string} val * @param {string} val
* @param {number} expire * @param {number} expire
*/ */
async setVal(key, val, expire = this._expire) { async setVal (key, val, expire = this._expire) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._conn.set(key, val, expire, err => { this._conn.set(key, val, expire, err => {
if (err) return reject(err); if (err) return reject(err)
return resolve(null); return resolve(null)
}) })
}) })
} }
/** /**
* get object from memcached * get object from memcached
* @param {string} key * @param {string} key
*/ */
async getVal(key) { async getVal (key) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._conn.get(key, (err, data) => { this._conn.get(key, (err, data) => {
if (err) return reject(err); if (err) return reject(err)
return resolve(data); return resolve(data)
}) })
}) })
} }
set host(str) { this._host = str } set host (str) { this._host = str }
set port(str) { this._port = str } set port (str) { this._port = str }
set expire(str) { this._expire = str } set expire (str) { this._expire = str }
} }
module.exports = new memcachedLib(); module.exports = new MemcachedLib()

View File

@ -1,40 +1,40 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose')
const tokenSchema = mongoose.Schema({ const tokenSchema = mongoose.Schema({
object: Object, object: Object,
expire: { expire: {
type: Number, type: Number,
default: Date.now default: Date.now
} }
}); })
tokenSchema.statics.clearExpire = function (cb) { tokenSchema.statics.clearExpire = function (cb) {
console.log(Date.now()) console.log(Date.now())
return this.remove({ expire: { $lte: Date.now() } }, cb); return this.remove({ expire: { $lte: Date.now() } }, cb)
} }
tokenSchema.statics.renewToken = function (id, expire, cb) { tokenSchema.statics.renewToken = function (id, expire, cb) {
return this.update({ _id: mongoose.Schema.Types.ObjectId(id) }, { $set: { expire: Date.now() + 86400000 } }, cb); return this.update({ _id: mongoose.Schema.Types.ObjectId(id) }, { $set: { expire: Date.now() + 86400000 } }, cb)
} }
tokenSchema.statics.checkToken = async function (str) { tokenSchema.statics.checkToken = async function (str) {
let self = this; let self = this
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
self.findOne({ _id: str, expire: { $gte: Date.now() } }, (err, row) => { self.findOne({ _id: str, expire: { $gte: Date.now() } }, (err, row) => {
if (err || !row) return resolve(false); if (err || !row) return resolve(false)
return resolve(true); return resolve(true)
});
}) })
})
} }
tokenSchema.statics.getToken = async function (str) { tokenSchema.statics.getToken = async function (str) {
let self = this; let self = this
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
self.findOne({ _id: str, expire: { $gte: Date.now() } }, (err, row) => { self.findOne({ _id: str, expire: { $gte: Date.now() } }, (err, row) => {
if (err) return reject(err); if (err) return reject(err)
return resolve(row); return resolve(row)
})
}) })
})
} }
const token = mongoose.model('token', tokenSchema, 'token'); const Token = mongoose.model('token', tokenSchema, 'token')
module.exports = { module.exports = {
token Token
} }

View File

@ -1,89 +1,88 @@
const mysql = require('mysql'); const mysql = require('mysql')
class MySQLPool { class MySQLPool {
constructor() { constructor () {
this._user = ''; this._user = ''
this._password = ''; this._password = ''
this._host = ''; this._host = ''
this._port = 3306; this._port = 3306
this._database = ''; this._database = ''
this._socketPath = '' this._socketPath = ''
this._pool = null; this._pool = null
this.autoclose = false; this.autoclose = false
this._useSocket = false; this._useSocket = false
}
createPool () {
let json = {
connectionLimit: 30,
user: this._user,
password: this._password,
host: this._host,
port: this._port,
socketPath: this._socketPath
}
if (this._useSocket) {
delete json.host
delete json.port
} else {
delete json.socketPath
}
this._pool = mysql.createPool(json)
}
async getConn () {
return new Promise((resolve, reject) => {
this._pool.getConnection((err, conn) => {
if (err) return reject(err)
return resolve(conn)
})
})
}
formatQuery (query, arg) {
return mysql.format(query, arg)
}
escape (val) {
return mysql.escape(val)
}
recordPage (rows, page, maxPage) {
if (!page || !isFinite(page) || page < 1) page = 1
let totalPage = Math.ceil(rows / maxPage)
let prevPage = page - 1
let nextPage = page + 1
if (prevPage < 1) prevPage = 1
if (nextPage > totalPage) nextPage = totalPage
let recStart = (page - 1) * maxPage + 1
let recEnd = (recStart + maxPage - 1)
if (recEnd > rows) recEnd = rows
let json = {
recStart,
recEnd,
total: rows,
prevPage,
nextPage,
totalPage,
page
} }
createPool() { return json
let json = { }
connectionLimit: 30,
user: this._user,
password: this._password,
host: this._host,
port: this._port,
socketPath: this._socketPath
};
if (this._useSocket) {
delete json.host;
delete json.port;
} else {
delete json.socketPath;
}
this._pool = mysql.createPool(json);
}
async getConn() { set user (str) { this._user = str }
return new Promise((resolve, reject) => { set host (str) { this._host = str }
this._pool.getConnection((err, conn) => { set password (str) { this._password = str }
if (err) return reject(err); set port (str) { this._port = str }
return resolve(conn) set database (str) { this._database = str }
})
})
}
formatQuery(query, arg) {
return mysql.format(query, arg);
}
escape(val) {
return mysql.escape(val);
}
recordPage(rows, page, maxPage) {
if (!page || !isFinite(page) || page < 1) page = 1;
let totalpage = Math.ceil(rows / maxPage);
let prevpage = page - 1;
let nextpage = page + 1;
if (prevpage < 1) prevpage = 1;
if (nextpage > totalpage) nextpage = totalpage;
let rec_start = (page - 1) * maxPage + 1
let rec_end = (rec_start + maxPage - 1);
if (rec_end > rows) rec_end = rows;
let json = {
rec_start,
rec_end,
total: rows,
prevpage,
nextpage,
totalpage,
page
};
return json;
}
set user(str) { this._user = str; }
set host(str) { this._host = str; }
set password(str) { this._password = str; }
set port(str) { this._port = str; }
set database(str) { this._database = str; }
} }
// let Pool = ((opts) => { // let Pool = ((opts) => {
// let defOpts = { // let defOpts = {
// user: 'root', // user: 'root',
@ -116,4 +115,4 @@ class MySQLPool {
// return pool // return pool
// })() // })()
module.exports = new MySQLPool(); module.exports = new MySQLPool()

View File

@ -1,35 +1,35 @@
const nodemailer = require('nodemailer'); const nodemailer = require('nodemailer')
const config = require('../config.json'); const config = require('../config.json')
const util = require('util'); const util = require('util')
module.exports = async(toMail, template = {}, data = []) => { module.exports = async(toMail, template = {}, data = []) => {
let transporter = nodemailer.createTransport({ let transporter = nodemailer.createTransport({
host: config.smtp.host, host: config.smtp.host,
port: config.smtp.port, port: config.smtp.port,
secure: config.smtp.secure, // secure:true for port 465, secure:false for port 587 secure: config.smtp.secure, // secure:true for port 465, secure:false for port 587
auth: { auth: {
user: config.smtp.user, user: config.smtp.user,
pass: config.smtp.pass pass: config.smtp.pass
} }
}); })
// setup email data with unicode symbols // setup email data with unicode symbols
let mailOptions = { let mailOptions = {
from: config.smtp.sys_mail, // sender address from: config.smtp.sys_mail, // sender address
to: toMail, // list of receivers to: toMail, // list of receivers
subject: template.title || '', // Subject line subject: template.title || '', // Subject line
text: template.text ? util.format(template.text, ...data) : '', // plain text body text: template.text ? util.format(template.text, ...data) : '', // plain text body
html: template.html ? util.format(template.html, ...data) : '' // html body html: template.html ? util.format(template.html, ...data) : '' // html body
}; }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// send mail with defined transport object // send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => { transporter.sendMail(mailOptions, (error, info) => {
if (error) { if (error) {
return reject(error); return reject(error)
} }
// console.log('Mepassage %s sent: %s', info.messageId, info.response); // console.log('Mepassage %s sent: %s', info.messageId, info.response);
return resolve(info); return resolve(info)
}); })
}); })
} }

View File

@ -1,68 +1,74 @@
const StoreObj = (() => { const StoreObj = (() => {
let memStore = {}
let maxAge = 86400000
let memStore = {}; /**
let maxAge = 86400000; * @param {string} uuid
* @param {object} obj
/** */
* @param {string} uuid const set = (uuid, obj) => {
* @param {object} obj memStore[uuid] = {
*/ obj,
const set = (uuid, obj) => { age: Date.now() + maxAge
memStore[uuid] = {
obj,
age: Date.now() + maxAge
}
} }
}
/** /**
* @param {string} uuid * @param {string} uuid
*/ */
const get = (uuid) => { const get = (uuid) => {
if (uuid in memStore) { if (uuid in memStore) {
let s = memStore[uuid]; let s = memStore[uuid]
if (Date.now() < s.age) { if (Date.now() < s.age) {
s.age = Date.now() + maxAge; s.age = Date.now() + maxAge
return s.obj; return s.obj
} else { } else {
delete memStore[uuid]; delete memStore[uuid]
} }
}
return null;
} }
return null
}
/** /**
* @param {string} uuid * @param {string} uuid
*/ */
const chkKey = (uuid) => { const chkKey = (uuid) => {
if (uuid in memStore) return true; if (uuid in memStore) return true
return false; return false
}
/**
* @param {string} uuid
*/
const del = (uuid) => {
if (uuid in memStore) delete memStore[uuid]
}
const clear = () => {
let t = Date.now()
for (var i in memStore) {
let s = memStore[i]
if (s.age < t) delete memStore[i]
} }
}
/** /**
* @param {string} uuid * @param {string} uuid if not input return all
*/ */
const del = (uuid) => { const show = (uuid) => {
if (uuid in memStore) delete memStore[uuid]; if (uuid && uuid in memStore) return memStore[uuid]
}
const clear = () => { return memStore
let t = Date.now(); }
for (var i in memStore) {
let s = memStore[i];
if (s.age < t) delete memStore[i];
}
}
/** return {
* @param {string} uuid if not input return all set,
*/ get,
const show = (uuid) => { chkKey,
if (uuid && uuid in memStore) return memStore[uuid]; clear,
del,
return memStore; show
} }
return {set, get, chkKey, clear, del, show };
})() })()
module.exports = StoreObj; module.exports = StoreObj

View File

@ -4,6 +4,9 @@
"main": "app.js", "main": "app.js",
"author": "UrWind", "author": "UrWind",
"license": "MIT", "license": "MIT",
"scripts": {
"check": "standard --fix --verbose"
},
"dependencies": { "dependencies": {
"kcors": "2", "kcors": "2",
"koa": "^2.2.0", "koa": "^2.2.0",
@ -16,5 +19,8 @@
"mongoose": "^4.10.4", "mongoose": "^4.10.4",
"mysql": "^2.13.0", "mysql": "^2.13.0",
"nodemailer": "^4.0.1" "nodemailer": "^4.0.1"
},
"devDependencies": {
"standard": "^10.0.2"
} }
} }

View File

@ -1,194 +1,193 @@
const Router = require('koa-router'); /* eslint-disable no-throw-literal */
const router = new Router(); /* eslint-env es6 */
/* eslint-disable no-multi-str */
const Router = require('koa-router')
const router = new Router()
// import tools // import tools
const crypto = require('../../libs/crypto.js'); const crypto = require('../../libs/crypto.js')
const so = require('../../libs/storeObject'); // const so = require('../../libs/storeObject')
const mongo = require('../../libs/mongo_model.js'); const mongo = require('../../libs/mongo_model.js')
const mem = require('../../libs/memcache_lib'); const mem = require('../../libs/memcache_lib')
const msgMng = require('./msgManager'); const msgMng = require('./msgManager')
const sendmail = require('../../libs/sendmail'); const sendmail = require('../../libs/sendmail')
router router
.post('/user', async(c, n) => { .post('/user', async(c, n) => {
let arr = c.request.body; let arr = c.request.body
if (!arr.data) throw 'CE0000'; if (!arr.data) throw 'CE0000'
if (!arr.data.account) throw 'CE0001'; if (!arr.data.account) throw 'CE0001'
if (!arr.data.password) throw 'CE00002'; if (!arr.data.password) throw 'CE00002'
if (!arr.data.name) throw 'CE0004'; if (!arr.data.name) throw 'CE0004'
if (!arr.data.email) throw 'CE0005'; if (!arr.data.email) throw 'CE0005'
try { try {
let query = "select count(*) as c from ??.?? where `account` = ?"; let query = 'select count(*) as c from ??.?? where `account` = ?'
let param = ['lora', 'user', arr.data.account]; let param = ['lora', 'user', arr.data.account]
let count = await c.syncQuery(query, param); let count = await c.syncQuery(query, param)
if (count.length == 0) throw 'SE0000'; if (count.length === 0) throw 'SE0000'
if (count[0].c > 0) throw 'CE0006'; if (count[0].c > 0) throw 'CE0006'
} catch (err) { } catch (err) {
if (typeof err == 'string') throw err; if (typeof err === 'string') throw err
c.serr = err; c.serr = err
throw 'SE0000'; throw 'SE0000'
} }
let uid = 0; let uid = 0
try { try {
let query = "insert into ??.?? (`account`, `password`, `name`, `email`) values (?, ?, ?, ?)"; let query = 'insert into ??.?? (`account`, `password`, `name`, `email`) values (?, ?, ?, ?)'
let param = ['lora', 'user', arr.data.account, arr.data.password, arr.data.name, arr.data.email]; let param = ['lora', 'user', arr.data.account, arr.data.password, arr.data.name, arr.data.email]
let indata = await c.syncQuery(query, param); let indata = await c.syncQuery(query, param)
uid = indata.insertId; uid = indata.insertId
} catch (err) { } catch (err) {
if (typeof err == 'string') throw err; if (typeof err === 'string') throw err
c.serr = err; c.serr = err
throw 'SE0001'; throw 'SE0001'
} }
c.body = { c.body = {
record: [{ uid }] record: [{ uid }]
} }
}) })
.get('/user/:uid', async(c, n) => { .get('/user/:uid', async(c, n) => {
if (!await mongo.token.checkToken(c.token)) throw 'CE1000'; if (!await mongo.Token.checkToken(c.token)) throw 'CE1000'
try { try {
let t = await mongo.token.getToken(c.token); let t = await mongo.Token.getToken(c.token)
if (t.object.uid != c.params.uid) throw 'CE2000'; if (t.object.uid !== c.params.uid) throw 'CE2000'
} catch (err) { } catch (err) {
if (typeof err == 'string') throw err; if (typeof err === 'string') throw err
c.serr = err; c.serr = err
throw 'SE0000'; throw 'SE0000'
} }
try { try {
let user = await c.syncQuery('select `uid`,`account`,`name`,`email` from ??.?? where `uid` = ?', ['lora', 'user', c.params.uid]); let user = await c.syncQuery('select `uid`,`account`,`name`,`email` from ??.?? where `uid` = ?', ['lora', 'user', c.params.uid])
c.body = {
record: user
}
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0000';
}
})
.put('/user/:uid', async(c, n) => {
if (!await mongo.token.checkToken(c.token)) throw 'CE1000';
let arr = c.request.body;
if (!arr.data) throw 'CE0000';
if (!arr.data.name) throw 'CE0004';
if (!arr.data.email) throw 'CE0005';
try {
let t = await mongo.token.getToken(c.token);
if (t.object.uid != c.params.uid) throw 'CE2000';
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0000';
}
try {
let query = "update ??.?? set \
`name` = ?, \
`email` = ?" + (arr.data.password ? ',' : '') + " \
" + (arr.data.password ? "`password` = ?, " : '') + " \
where \
`uid` = ?";
let param = ['lora', 'user', arr.data.name, arr.data.email];
if (arr.data.password) param.push(crypto.genPassHash(arr.data.password));
param.push(c.params.uid);
let updata = await c.syncQuery(query, param);
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0002';
}
c.body = { record: [] };
})
.post('/login', async(c, n) => {
let arr = c.request.body;
if (!arr.data) throw 'CE0000';
if (!arr.data.account) throw 'CE0001';
if (!arr.data.password) throw 'CE0002';
try {
let user = await c.syncQuery('select `uid`,`account`,`password`,`name`,`email` from ??.?? where `account` = ?', ['lora', 'user', arr.data.account])
if (user.length == 0) throw 'CE0003';
if (!crypto.comparePass(arr.data.password, user[0].password)) throw 'CE0003';
delete user[0].password;
c.body = {
record: user
}
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0000';
}
let u = c.body.record[0];
let token = new mongo.token({ object: u, expire: Date.now() + 86400000 });
token.save();
c.body.rt = {
token: {
id: token._id
}
}
})
.post('/user/forgotpass', async(c, n) => {
let arr = c.request.body;
if (!arr.data) throw 'CE0000';
if (!arr.data.account) throw 'CE0001';
if (!arr.data.email) throw 'CE0005';
let user = [];
try {
let query = "select * from ??.?? where `account` = ? and `email` = ?";
let param = ['lora', 'user', arr.data.account, arr.data.email];
user = await c.syncQuery(query, param);
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0001';
}
if (user.length == 0) throw 'CE0007';
let randomToken = crypto.random(10);
try {
await mem.setVal(randomToken, JSON.stringify(user[0]), 7200);
} catch (err) {
c.serr = err;
throw 'SE0005';
}
try {
await sendmail(user[0].email, msgMng.getMailTemplate('forgotpass', c.headers['accept-language']), [randomToken])
} catch (err) {
if (typeof err == 'string') throw err;
c.serr = err;
throw 'SE0006';
}
c.body = { c.body = {
record: [] record: user
} }
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0000'
}
})
.put('/user/:uid', async(c, n) => {
if (!await mongo.Token.checkToken(c.token)) throw 'CE1000'
let arr = c.request.body
if (!arr.data) throw 'CE0000'
if (!arr.data.name) throw 'CE0004'
if (!arr.data.email) throw 'CE0005'
try {
let t = await mongo.Token.getToken(c.token)
if (t.object.uid !== c.params.uid) throw 'CE2000'
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0000'
}
try {
let query = 'update ??.?? set \
`name` = ?, \
`email` = ?' + (arr.data.password ? ',' : '') + ' \
' + (arr.data.password ? '`password` = ?, ' : '') + ' \
where \
`uid` = ?'
let param = ['lora', 'user', arr.data.name, arr.data.email]
if (arr.data.password) param.push(crypto.genPassHash(arr.data.password))
param.push(c.params.uid)
await c.syncQuery(query, param)
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0002'
}
c.body = { record: [] }
})
.post('/login', async(c, n) => {
let arr = c.request.body
if (!arr.data) throw 'CE0000'
if (!arr.data.account) throw 'CE0001'
if (!arr.data.password) throw 'CE0002'
try {
let user = await c.syncQuery('select `uid`,`account`,`password`,`name`,`email` from ??.?? where `account` = ?', ['lora', 'user', arr.data.account])
if (user.length === 0) throw 'CE0003'
if (!crypto.comparePass(arr.data.password, user[0].password)) throw 'CE0003'
delete user[0].password
c.body = {
record: user
}
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0000'
}
let u = c.body.record[0]
let token = new mongo.Token({ object: u, expire: Date.now() + 86400000 })
token.save()
c.body.rt = {
token: {
id: token._id
}
}
})
.post('/user/forgotpass', async(c, n) => {
let arr = c.request.body
if (!arr.data) throw 'CE0000'
if (!arr.data.account) throw 'CE0001'
if (!arr.data.email) throw 'CE0005'
let user = []
try {
let query = 'select * from ??.?? where `account` = ? and `email` = ?'
let param = ['lora', 'user', arr.data.account, arr.data.email]
user = await c.syncQuery(query, param)
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0001'
}
if (user.length === 0) throw 'CE0007'
let randomToken = crypto.random(10)
try {
await mem.setVal(randomToken, JSON.stringify(user[0]), 7200)
} catch (err) {
c.serr = err
throw 'SE0005'
}
try {
await sendmail(user[0].email, msgMng.getMailTemplate('forgotpass', c.headers['accept-language']), [randomToken])
} catch (err) {
if (typeof err === 'string') throw err
c.serr = err
throw 'SE0006'
}
c.body = {
record: []
}
}) })
.post('/user/resetpass', async(c, n) => { .post('/user/resetpass', async(c, n) => {
let arr = c.request.body; let arr = c.request.body
if (!arr.data) throw 'CE0000'; if (!arr.data) throw 'CE0000'
if (!arr.data.account) throw 'CE0001'; if (!arr.data.account) throw 'CE0001'
if (arr.data.resettype != 'pass' && arr.data.resettype != 'token') throw 'CE0008'; if (arr.data.resettype !== 'pass' && arr.data.resettype !== 'token') throw 'CE0008'
if (arr.data.resettype == 'pass') { if (arr.data.resettype === 'pass') {
if (!arr.data.password) throw 'CE0002'; if (!arr.data.password) throw 'CE0002'
} else { } else {
if (!arr.data.token) throw 'CE0009'; if (!arr.data.token) throw 'CE0009'
} }
if (!arr.data.newpass) throw 'CE0002'; if (!arr.data.newpass) throw 'CE0002'
}) })
module.exports = router
module.exports = router;

View File

@ -1,73 +1,72 @@
const Router = require('koa-router'); const Router = require('koa-router')
const router = new Router(); const router = new Router()
const koaBody = require('koa-body'); const koaBody = require('koa-body')
// import tools // import tools
const mysql = require('../../libs/mysql_pool.js'); const mysql = require('../../libs/mysql_pool.js')
const so = require('../../libs/storeObject'); // const so = require('../../libs/storeObject')
const config = require('../../config.json'); // const config = require('../../config.json')
const msgMng = require('./msgManager'); const msgMng = require('./msgManager')
// routes // routes
const account_api = require('./account.js'); const accountApi = require('./account.js')
// api response handler // api response handler
router.use(async(c, n) => { router.use(async(c, n) => {
// get MySQL connection // get MySQL connection
c.db = await mysql.getConn(); c.db = await mysql.getConn()
// set Async/Await Query // set Async/Await Query
c.syncQuery = (query, param = null) => { c.syncQuery = (query, param = null) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (param != null) { if (param != null) {
c.db.query(query, param, (err, row) => { c.db.query(query, param, (err, row) => {
if (err) return reject(err); if (err) return reject(err)
return resolve(row) return resolve(row)
});
} else {
c.db.query(query, (err, row) => {
if (err) return reject(err);
return resolve(row)
});
}
}) })
} } else {
c.token = c.headers['x-auth-token'] || ''; c.db.query(query, (err, row) => {
if (err) return reject(err)
return resolve(row)
})
}
})
}
c.token = c.headers['x-auth-token'] || ''
// console.log(c.headers['accept-language']) // console.log(c.headers['accept-language'])
try { try {
await n(); await n()
c.body = { c.body = {
data: c.body, data: c.body,
status: 1 status: 1
}
} catch (e) {
let msg = msgMng.getMsg(e, c.headers['accept-language']);
c.body = {
errorCode: e,
message: msg,
servErr: c.serr ? c.serr.toString() : '',
status: 0
}
if (e[0] == 'C' || e[0] == 'c') c.status = 400;
if (e[0] == 'S' || e[0] == 's') c.status = 500;
} }
if ('db' in c && typeof c.db == 'object' && 'release' in c.db && typeof c.db.release == 'function') c.db.release(); } catch (e) {
let msg = msgMng.getMsg(e, c.headers['accept-language'])
c.body = {
errorCode: e,
message: msg,
servErr: c.serr ? c.serr.toString() : '',
status: 0
}
if (e[0] === 'C' || e[0] === 'c') c.status = 400
if (e[0] === 'S' || e[0] === 's') c.status = 500
}
if ('db' in c && typeof c.db === 'object' && 'release' in c.db && typeof c.db.release === 'function') c.db.release()
}) })
// enable bodyParser // enable bodyParser
router.all('*', koaBody({ router.all('*', koaBody({
multipart: true, multipart: true,
// upload file size 10mb // upload file size 10mb
maxFieldSize: 10 * 1024 * 1024 maxFieldSize: 10 * 1024 * 1024
}), async(c, n) => { await n(); }) }), async(c, n) => { await n() })
router router
.get('/', async(c, n) => { .get('/', async(c, n) => {
c.body = { c.body = {
msg: 'API Endpoint' msg: 'API Endpoint'
}; }
}) })
.use('/account', account_api.routes()) .use('/account', accountApi.routes())
module.exports = router; module.exports = router

View File

@ -1,46 +1,46 @@
const fs = require('fs'); // const fs = require('fs')
const path = require('path'); // const path = require('path')
class msgManager { class MsgManager {
constructor() { constructor () {
this.errs = {}; this.errs = {}
this.defLang = 'zh'; this.defLang = 'zh'
let err = require(`./language/zh`); let err = require(`./language/zh`)
this.errs['zh'] = err; this.errs['zh'] = err
}
checkLang (lang = '') {
let lng = this.defLang
if (typeof lang === 'string' && lang.trim().length > 0) {
let l = lang.split(',')
if (l.length > 0) {
let tmp = l[0].substring(0, 2)
if (tmp.trim().length > 0) lng = tmp
}
} }
checkLang(lang = '') { if (!(lng in this.errs)) {
let lng = this.defLang; try {
if (typeof lang == 'string' && lang.trim().length > 0) { let errs = require(`./language/${lng}`)
let l = lang.split(','); this.errs[lng] = errs
if (l.length > 0) { } catch (err) {
let tmp = l[0].substring(0, 2); lng = this.defLang
if (tmp.trim().length > 0) lng = tmp; }
}
}
if (!(lng in this.errs)) {
try {
let errs = require(`./language/${lng}`);
this.errs[lng] = errs;
} catch (err) {
lng = this.defLang;
}
}
return lng;
} }
return lng
}
getMsg(code, lang = '') { getMsg (code, lang = '') {
let lng = this.checkLang(lang); let lng = this.checkLang(lang)
return this.errs[lng][code] || 'errorCode not found'; return this.errs[lng][code] || 'errorCode not found'
} }
getMailTemplate(type, lang = '') { getMailTemplate (type, lang = '') {
let lng = this.checkLang(lang); let lng = this.checkLang(lang)
return this.errs[lng]['mail'][type] || {}; return this.errs[lng]['mail'][type] || {}
} }
} }
module.exports = new msgManager(); module.exports = new MsgManager()

View File

@ -1,33 +1,33 @@
module.exports = { module.exports = {
// client error // client error
CE0000: '請輸入參數', CE0000: '請輸入參數',
CE0001: '請輸入帳號', CE0001: '請輸入帳號',
CE0002: '請輸入密碼', CE0002: '請輸入密碼',
CE0003: '使用者帳號或密碼錯誤', CE0003: '使用者帳號或密碼錯誤',
CE0004: '請輸入使用者名稱', CE0004: '請輸入使用者名稱',
CE0005: '請輸入Email', CE0005: '請輸入Email',
CE0006: '使用者帳號重複', CE0006: '使用者帳號重複',
CE0007: '查無使用者資料', CE0007: '查無使用者資料',
CE0008: '重設密碼類型輸入錯誤', CE0008: '重設密碼類型輸入錯誤',
CE0009: '請輸入重設密碼Token', CE0009: '請輸入重設密碼Token',
CE1000: 'Token驗證失敗', CE1000: 'Token驗證失敗',
CE2000: '使用者權限不足', CE2000: '使用者權限不足',
// server error // server error
SE0000: '資料查詢失敗', SE0000: '資料查詢失敗',
SE0001: '資料新增失敗', SE0001: '資料新增失敗',
SE0002: '資料更新失敗', SE0002: '資料更新失敗',
SE0003: '資料刪除失敗', SE0003: '資料刪除失敗',
SE0005: '快取資料設定失敗', SE0005: '快取資料設定失敗',
SE0006: 'Email發送失敗', SE0006: 'Email發送失敗',
// email template // email template
mail: { mail: {
forgotpass: { forgotpass: {
title: '忘記密碼信件', title: '忘記密碼信件',
text: '以下是重置密碼專用Token有效時間為2小時\n如果沒有申請此操作請忽略此信件\n重置Token: %s', text: '以下是重置密碼專用Token有效時間為2小時\n如果沒有申請此操作請忽略此信件\n重置Token: %s',
html: '以下是重置密碼專用Token有效時間為2小時<br />如果沒有申請此操作請忽略此信件<br />重置Token: %s' html: '以下是重置密碼專用Token有效時間為2小時<br />如果沒有申請此操作請忽略此信件<br />重置Token: %s'
}
} }
} }
}

File diff suppressed because it is too large Load Diff