first
This commit is contained in:
commit
d4f9e78e2a
25
.drone.yml
Normal file
25
.drone.yml
Normal 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
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
doc
|
||||
config/dev-config.js
|
||||
package-lock.json
|
||||
notes
|
||||
.vscode
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "common-libs"]
|
||||
path = common-libs
|
||||
url = https://github.com/ViewSonicCloud/backend-libs.git
|
33
app.js
Normal file
33
app.js
Normal 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
11
config/index.js
Normal 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
21
docker/Dockerfile
Normal 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
3
index.js
Normal file
@ -0,0 +1,3 @@
|
||||
process.env.__BASE = __dirname
|
||||
|
||||
const server = require('./app')
|
83
libs/crypto.js
Normal file
83
libs/crypto.js
Normal 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
30
package.json
Normal 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
62
route/api/index.js
Normal 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
11
route/index.js
Normal 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
65
route/utils/index.js
Normal 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
|
||||
}
|
16
route/utils/message/index.js
Normal file
16
route/utils/message/index.js
Normal 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
10
test/api/index.js
Normal 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
17
test/index.js
Normal 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')
|
||||
})
|
Loading…
Reference in New Issue
Block a user