This commit is contained in:
Jay 2018-03-13 23:34:27 +08:00
commit d4f9e78e2a
15 changed files with 396 additions and 0 deletions

25
.drone.yml Normal file
View File

@ -0,0 +1,25 @@
pipeline:
build:
image: node:${NODE_VERSION}
environment:
- DB_HOST=database
- DB_PORT=5432
- DB_USER=postgres
- DB_NAME=mystorage
- NODE_ENV=test
- HOST_URL="http://localhost:10230"
commands:
- npm install
- npm run dbtool
- npm run test
services:
database:
image: postgres
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=mystorage
matrix:
NODE_VERSION:
- latest
- "8"
- "9"

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
node_modules
doc
config/dev-config.js
package-lock.json
notes
.vscode

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "common-libs"]
path = common-libs
url = https://github.com/ViewSonicCloud/backend-libs.git

33
app.js Normal file
View File

@ -0,0 +1,33 @@
const Koa = require('koa')
const app = new Koa()
const path = require('path')
const fs = require('fs')
const config = require('./config')
// require middleware
const cors = require('kcors')
const koaBody = require('koa-body')
const koaSession = require('koa-session2')
const koaLogger = require('koa-logger')
const koaMount = require('koa-mount')
const koaStatic = require('koa-static')
if (process.env['NODE_ENV'] !== 'test') {
app.use(koaLogger())
}
app.use(cors())
app.use(koaSession())
app.use(koaStatic(path.resolve(__dirname, 'public'), {
maxage: 600000
}))
const rootRouter = require('./route')
app.use(rootRouter.allowedMethods())
app.use(rootRouter.routes())
const server = app.listen(config.port, () => {
console.log(`start on port ${server.address().port}`)
})
module.exports = server

11
config/index.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
linkaddr: process.env.HOST_URL || 'localhost:10230',
port: process.env.PORT || 10230,
database: {
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 5432,
db: process.env.DB_NAME || 'mystorage',
user: process.env.DB_USER || 'postgres',
pass: process.env.DB_PASS || '',
}
}

21
docker/Dockerfile Normal file
View File

@ -0,0 +1,21 @@
# build docker file $ docker build -t vstorage:latest -f docker/Dockerfile .
FROM node:9
LABEL Author=Jay
ENV DB_HOST localhost
ENV DB_PORT 5432
ENV DB_USER postgres
ENV DB_PASS ""
ENV DB_NAME mystorage
ENV HOST_URL localhost
ENV AWS_KEY ""
ENV AWS_SECRET ""
ENV AWS_REGION ""
ENV S3_BUCKET ""
ENV NODE_ENV ""
ENV SESSION_KEY ""
RUN mkdir -p /data
WORKDIR /data
COPY / /data
RUN npm install
EXPOSE 10230
CMD ["npm", "start"]

3
index.js Normal file
View File

@ -0,0 +1,3 @@
process.env.__BASE = __dirname
const server = require('./app')

83
libs/crypto.js Normal file
View File

@ -0,0 +1,83 @@
var crypto = require('crypto')
/**
* @param {Number} len
*/
var random = (len = 32) => {
var buf = crypto.randomBytes(len)
return buf.toString('hex')
}
/**
*
* @param {string} str
*/
var sha256 = (str, tostr = 'base64') => {
return crypto.createHash('sha256').update(str).digest(tostr)
}
/**
*
* @param {string} str
*/
var genPassHash = (str) => {
var hash = random(16)
var pass = sha256(str + hash)
return `$${hash}$${pass}`
}
/**
*
* @param {string} plain
* @param {string} hash
*/
var comparePass = (plain, hash) => {
var match = hash.match(/^\$(.+?)\$(.+)$/)
if (match == null || match.length < 3 || !match[1] || !match[2]) return false
var pass = sha256(plain + match[1])
if (pass === match[2]) return true
return false
}
const pbkdf2 = (pass, salt, count, len, tostr = false) => {
let hlen = crypto.createHash('sha256').update('').digest().length
let blockCount = Math.ceil(len / hlen)
let s256 = (s) => { return crypto.createHash('sha256').update(s).digest() }
let out = []
for (let i = 0; i < blockCount; i++) {
let loopBuf = Buffer.alloc(4)
loopBuf.writeInt32BE(i)
let saltBuf = Buffer.from(salt)
let last = Buffer.concat([saltBuf, loopBuf], saltBuf.length + loopBuf.length)
let passBuf = Buffer.from(pass)
last = s256(Buffer.concat([passBuf, last], passBuf.length + last.length))
let xor = Buffer.from(last)
for (let j = 1; j < count; j++) {
last = s256(Buffer.concat([passBuf, last], passBuf.length + last.length))
xor = last.map((t, idx) => {
return t ^ xor[idx]
})
}
out.push(xor)
}
let olen = 0
for (let i in out) {
olen += out[i].length
}
let raw = Buffer.concat([...out], olen)
if (!tostr) {
return raw.slice(0, len)
} else {
return Buffer.from(raw.slice(0, len)).toString('hex')
}
}
module.exports = {
random,
sha256,
genPassHash,
comparePass,
pbkdf2
}

30
package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "mystorage_v2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"check": "standard --fix --verbose",
"test": "mocha --exit test/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"kcors": "^2.2.1",
"koa": "^2.5.0",
"koa-body": "^2.5.0",
"koa-logger": "^3.2.0",
"koa-mount": "^3.0.0",
"koa-router": "^7.4.0",
"koa-session2": "^2.2.5",
"koa-static": "^4.0.2"
},
"devDependencies": {
"chai": "^4.1.2",
"chai-http": "^3.0.0",
"mocha": "^4.1.0",
"standard": "^10.0.3"
}
}

62
route/api/index.js Normal file
View File

@ -0,0 +1,62 @@
const Router = require('koa-router')
const r = new Router()
const {
resObject,
MError
} = require('../utils')
r.use(async(c, n) => {
c.obj = c.obj || {}
c.chkBody = function (key = '', type = '', empty = false) {
const uuidChk = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
if (!(key in c.request.body)) return false
switch (type) {
case 'string':
if (typeof c.request.body[key] !== 'string' || (!empty && !c.request.body[key])) return false
break
case 'number':
if (!isFinite(c.request.body[key])) return false
break
case 'boolean':
if (typeof c.request.body[key] !== 'boolean') return false
break
case 'array':
if (!Array.isArray(c.request.body[key]) || (!empty && c.request.body[key].length === 0)) return false
break
case 'uuid':
if (typeof c.request.body[key] !== 'string') return false
if (!empty && c.request.body[key] === '') return false
if (!empty && !uuidChk.test(c.request.body[key])) return false
break
default:
return false
}
return true
}
let obj = null
try {
await n()
} catch (e) {
console.log(e)
obj = resObject(e instanceof MError ? e.mtype : 'InternalError', e.msg || '')
}
if (Object.keys(c.obj).length > 0 && 'status' in c.obj && 'obj' in c.obj) {
c.status = c.obj.status
c.body = c.obj.obj
}
if (obj !== null) {
c.status = obj.status
c.body = obj.obj
}
})
r.get('/', async (c, n) => {
c.obj = resObject('Success')
})
module.exports = r

11
route/index.js Normal file
View File

@ -0,0 +1,11 @@
const Router = require('koa-router')
const r = new Router()
r.use('/api', require('./api').routes())
r.get('/', async (c, n) => {
c.status = 200
c.body = ""
})
module.exports = r

65
route/utils/index.js Normal file
View File

@ -0,0 +1,65 @@
const message = require('./message')
/**
* api response message util
* @param {String} key
* @param {String} msg
*/
const resObject = function (key = '', msg = null) {
if (!key || !(key in message)) {
// default message
return
}
let obj = Object.assign({}, message[key])
if (typeof msg === 'string' && msg.length > 0) obj.obj.message = msg
if (msg !== null && typeof msg === 'object') obj.obj = msg
return obj
}
const genError = function (type, msg = '') {
let err = new MError()
err.mtype = type
err.msg = msg
return err
}
class MError extends Error {
/**
* @param {String} str
*/
constructor (str) {
super(str)
this._mtype = ''
this._msg = ''
}
/**
* @param {String} type
*/
set mtype (type = '') {
this._mtype = type
}
get mtype () {
return this._mtype
}
/**
* @param {String} s
*/
set msg (s = '') {
this._msg = s
}
get msg () {
return this._msg
}
}
module.exports = {
resObject,
MError,
genError
}

View File

@ -0,0 +1,16 @@
module.exports = {
Success: {
status: 200,
obj: {
resCode: 0,
message: 'success'
}
},
InternalError: {
status: 500,
obj: {
resCode: 500,
message: 'Internal Error'
}
}
}

10
test/api/index.js Normal file
View File

@ -0,0 +1,10 @@
it('api root test', done => {
chai.request(server)
.get('/api')
.end((err, res) => {
chai.expect(err).to.be.null
chai.expect(res).to.be.status(200)
done()
})
})

17
test/index.js Normal file
View File

@ -0,0 +1,17 @@
process.env['NODE_ENV'] = 'test'
global.chai = require('chai')
global.chaiHttp = require('chai-http')
global.server = require('../app')
global.chai.use(chaiHttp)
global.importTest = (name, path) => {
describe(name, () => {
require(path)
})
}
describe('Project Test', () => {
importTest('Test API', './api')
})