import
This commit is contained in:
parent
52ed0c87e6
commit
e58fd0a27b
189
index.js
189
index.js
@ -2,14 +2,23 @@ import nedb from 'nedb'
|
|||||||
import express from 'express'
|
import express from 'express'
|
||||||
import expressWs from 'express-ws'
|
import expressWs from 'express-ws'
|
||||||
import session from 'express-session'
|
import session from 'express-session'
|
||||||
//import random from 'string-random'
|
import connect from 'connect-nedb-session'
|
||||||
|
import random from 'string-random'
|
||||||
import formidable from 'formidable'
|
import formidable from 'formidable'
|
||||||
|
import md5 from 'md5-node'
|
||||||
|
import { resolve } from 'path/posix'
|
||||||
|
|
||||||
|
|
||||||
|
process.on('SIGINT', function() {
|
||||||
|
console.log('Got SIGINT. Press Control-D/Control-C to exit.');
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
const app = expressWs(express()).app
|
const app = expressWs(express()).app
|
||||||
//const NedbStore = connect(session)
|
const NedbStore = connect(session)
|
||||||
|
|
||||||
// 自动载入所有库
|
|
||||||
// 自动构建 db 列表
|
// 数据: 自动构建 db 列表 或自动载入所有库
|
||||||
const databases = new Map()
|
const databases = new Map()
|
||||||
const db = (name) => (databases.get(name) || function(){
|
const db = (name) => (databases.get(name) || function(){
|
||||||
let database = new nedb({filename:`./data/db/${name}.db`,autoload:true,timestampData:true})
|
let database = new nedb({filename:`./data/db/${name}.db`,autoload:true,timestampData:true})
|
||||||
@ -17,75 +26,149 @@ const db = (name) => (databases.get(name) || function(){
|
|||||||
return database
|
return database
|
||||||
}())
|
}())
|
||||||
|
|
||||||
|
// 缓存: 自动构建 ws 列表
|
||||||
|
const wsstores = new Map()
|
||||||
|
const wsstore = name => (wsstores.get(name) || function() {
|
||||||
|
let list = new Map()
|
||||||
|
wsstores.set(name, list)
|
||||||
|
return list
|
||||||
|
}())
|
||||||
|
|
||||||
|
// 组件: 要求登录
|
||||||
|
const online = function(req, res, next) {
|
||||||
|
req.session.account ? next() : res.status(401).send('未登录')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件: 管理权限
|
||||||
|
const admin = function(req, res, next) {
|
||||||
|
req.session.account.gid === 1 ? next() : res.status(403).send('没有权限')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件: 移除输入非法信息
|
||||||
|
const remove = function(req, res, next) {
|
||||||
|
delete req.body._id
|
||||||
|
delete req.body.uid
|
||||||
|
delete req.body.createdAt
|
||||||
|
delete req.body.updatedAt
|
||||||
|
delete req.body.views
|
||||||
|
delete req.body.posts
|
||||||
|
delete req.body.likes
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件: 从缓存载入数据
|
||||||
|
|
||||||
|
// 组件: 操作权限
|
||||||
|
//const authority = function(req, res, next) {
|
||||||
|
// (req.method === 'GET') ? next() : res.status(200).send
|
||||||
|
//}
|
||||||
|
|
||||||
|
// 组件: 移除输出敏感信息
|
||||||
|
|
||||||
|
|
||||||
|
app.use(express.json())
|
||||||
|
app.use(express.urlencoded({ extended: false }))
|
||||||
|
app.use(session({
|
||||||
|
secret: 'keyboard cat',
|
||||||
|
name:'sid',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
cookie: { maxAge: 180 * 24 * 3600000 },
|
||||||
|
store: new NedbStore({filename: './data/db/session.db'}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
// 只允许管理权限访问
|
||||||
|
app.use('/session', online, admin)
|
||||||
|
app.use('/account', online, admin)
|
||||||
|
app.use('/message', online, admin)
|
||||||
|
app.use('/attach', online, admin)
|
||||||
|
app.use('/like', online, admin)
|
||||||
|
|
||||||
|
// 操作对象必须要登录
|
||||||
|
//app.use('/:name', )
|
||||||
|
|
||||||
// 对象列表
|
// 对象列表
|
||||||
|
|
||||||
|
|
||||||
// 对象实体
|
// 对象实体
|
||||||
// 对象附件
|
// 对象附件
|
||||||
// 对象评论
|
// 对象评论
|
||||||
// 对象收藏
|
// 对象收藏
|
||||||
// 对象点赞
|
// 对象点赞
|
||||||
app.get('/', function(req, res, next) {
|
|
||||||
res.send('index')
|
|
||||||
})
|
|
||||||
|
|
||||||
app.get('/test', function(req, res, next) {
|
|
||||||
res.send(`
|
|
||||||
<DOCTYPE html>
|
|
||||||
<title>test</title>
|
|
||||||
<p> 2333 <p>
|
|
||||||
<div id="div"></div>
|
|
||||||
<form id="form">
|
|
||||||
<input type="file" name="files" multiple accept=".jpg,">
|
|
||||||
<input id="btn" type="button" value="确认上传">
|
|
||||||
</form>
|
|
||||||
<script>
|
|
||||||
const btn = document.getElementById("btn");
|
|
||||||
const form = document.getElementById("form");
|
|
||||||
btn.onclick = function () {
|
|
||||||
console.log(1);
|
|
||||||
const formData = new FormData(form);
|
|
||||||
// 获取数组第一个文件
|
|
||||||
//files = formDate.get("files");
|
|
||||||
// 返回数组 获取所有文件
|
|
||||||
// files = formData.getAll("files");
|
|
||||||
// console.log(files);
|
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('post', '/demo/FmnKXZ8lxwGjf4GE/file');
|
|
||||||
xhr.send(formData);
|
|
||||||
xhr.onload = function () {
|
|
||||||
alert(xhr.responseText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// 无论在哪一级别的对象, 都是泛型对象, 因此不必二级restful
|
// 无论在哪一级别的对象, 都是泛型对象, 因此不必二级restful
|
||||||
// 列表也是对象
|
// 列表也是对象
|
||||||
//app.use('/:name', function(req, res, next) {
|
//app.use('/:name', function(req, res, next) {
|
||||||
// log
|
// log
|
||||||
//})
|
//})
|
||||||
|
|
||||||
|
const count_load = async function(name, query) {
|
||||||
|
await new Promise(resolve => db(name).count(query, function(err, count) {
|
||||||
|
resolve(count)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const list_load = async function(name, query) {
|
||||||
|
await new Promise(resolve => db(name).find(query, function(err, docs) {
|
||||||
|
let list = []
|
||||||
|
for (let doc of docs) list.push({_id: doc.id})
|
||||||
|
resolve(list)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
app.get('/:name', function(req, res, next) {
|
app.get('/:name', function(req, res, next) {
|
||||||
db(req.params.name).find({}, function(err, docs) {
|
if (req.query.tid) req.query.tid = Number(req.query.tid) // 某些查询参数需要转换类型(暂时)
|
||||||
|
if (req.query.top) req.query.top = Number(req.query.top) // 某些查询参数需要转换类型(暂时)
|
||||||
|
if (req.query.uid || req.query.uid !== req.session?.account?.uid) {
|
||||||
|
req.query.public = true // 如果查询条件限定为自己的, 则不用限制范围到公开的
|
||||||
|
}
|
||||||
|
let { pagesize, page, like, ...query } = req.query
|
||||||
|
pagesize = Number(pagesize) || 20
|
||||||
|
let skip = ((Number(page) || 1) - 1) * pagesize
|
||||||
|
|
||||||
|
// 基于登录状态的查询, 查询点赞过的, 查询评论过的
|
||||||
|
if (req.session?.account?.uid) {
|
||||||
|
if (like) query.$or = list_load('like',{name:req.params.name, uid:req.session.account.uid})
|
||||||
|
if (post) query.$or = list_load('post',{name:req.params.name, uid:req.session.account.uid})
|
||||||
|
}
|
||||||
|
db(req.params.name).find(query).skip(skip).limit(pagesize).sort({createdAt: -1}).exec(async function(err, docs) {
|
||||||
|
for (let item of docs) {
|
||||||
|
item.posts = await count_load('post', {name:req.params.name, id:item._id}) // 附加评论数量
|
||||||
|
item.likes = await count_load('like', {name:req.params.name, id:item._id}) // 附加点赞数量
|
||||||
|
if (user) item.user = await user_load(item.uid) // 附加用户信息
|
||||||
|
}
|
||||||
res.json(docs)
|
res.json(docs)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
app.put('/:name', function(req, res, next) {})
|
|
||||||
app.post('/:name', function(req, res, next) {
|
app.post('/:name', online, remove, function(req, res, next) {
|
||||||
db(req.params.name).insert({name:'2333'}, function(err, doc) {
|
req.body.uid = req.session.account.uid // 默认发布者uid
|
||||||
res.json(doc)
|
req.body.public = true // 默认发表即公开
|
||||||
|
db(req.params.name).insert(req.body, function(err, doc) {
|
||||||
|
doc ? res.json(doc) : res.status(500).send('内部错误')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
//app.put('/:name', online, function(req, res, next) {})
|
||||||
|
//app.patch('/:name', online, function(req, res, next) {})
|
||||||
|
//app.head('/:name', function(req, res, next) {})
|
||||||
|
//app.options('/:name', function(req, res, next) {})
|
||||||
|
app.get('/:name/:id', function(req, res, next) {
|
||||||
|
db(req.params.name).findOne({_id: req.params.id}, async function(err, doc) {
|
||||||
|
if (err || !doc) return res.status(404).send('目标资源不存在')
|
||||||
|
if (!doc.public && doc.uid !== req.session?.account?.uid) {
|
||||||
|
return res.status(403).send('没有权限读取')
|
||||||
|
}
|
||||||
|
// 附加用户信息
|
||||||
|
if (req.query.user) doc.user = await user_load(doc.uid)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
app.patch('/:name', function(req, res, next) {})
|
|
||||||
app.head('/:name', function(req, res, next) {})
|
|
||||||
app.options('/:name', function(req, res, next) {})
|
|
||||||
app.get('/:name/:id', function(req, res, next) {})
|
|
||||||
app.put('/:name/:id', function(req, res, next) {})
|
app.put('/:name/:id', function(req, res, next) {})
|
||||||
app.post('/:name/:id', function(req, res, next) {})
|
//app.post('/:name/:id', function(req, res, next) {})
|
||||||
app.patch('/:name/:id', function(req, res, next) {})
|
app.patch('/:name/:id', function(req, res, next) {})
|
||||||
app.options('/:name/:id', function(req, res, next) {})
|
//app.options('/:name/:id', function(req, res, next) {})
|
||||||
app.head('/:name/:id', function(req, res, next) {})
|
//app.head('/:name/:id', function(req, res, next) {})
|
||||||
|
|
||||||
app.get('/:name/:id/post', function(req, res, next) {
|
app.get('/:name/:id/post', function(req, res, next) {
|
||||||
// 获得此对象的所有post记录
|
// 获得此对象的所有post记录
|
||||||
|
@ -7,10 +7,13 @@
|
|||||||
"author": "satori <huan0016@gmail.com>",
|
"author": "satori <huan0016@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"connect-nedb-session": "^0.0.3",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-session": "^1.17.2",
|
"express-session": "^1.17.2",
|
||||||
"express-ws": "^5.0.2",
|
"express-ws": "^5.0.2",
|
||||||
"formidable": "^1.2.2",
|
"formidable": "^1.2.2",
|
||||||
"nedb": "^1.8.0"
|
"md5-node": "^1.0.1",
|
||||||
|
"nedb": "^1.8.0",
|
||||||
|
"string-random": "^0.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
yarn.lock
27
yarn.lock
@ -15,7 +15,7 @@ array-flatten@1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||||
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
||||||
|
|
||||||
async@0.2.10:
|
async@0.2.10, async@~0.2.8:
|
||||||
version "0.2.10"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
||||||
integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E=
|
integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E=
|
||||||
@ -48,6 +48,13 @@ bytes@3.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||||
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
||||||
|
|
||||||
|
connect-nedb-session@^0.0.3:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/connect-nedb-session/-/connect-nedb-session-0.0.3.tgz#e10f642d3d604f609bb23a450021dd1f0579c5ac"
|
||||||
|
integrity sha1-4Q9kLT1gT2CbsjpFACHdHwV5xaw=
|
||||||
|
dependencies:
|
||||||
|
nedb "0.0.6"
|
||||||
|
|
||||||
content-disposition@0.5.3:
|
content-disposition@0.5.3:
|
||||||
version "0.5.3"
|
version "0.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
||||||
@ -265,6 +272,11 @@ localforage@^1.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lie "3.1.1"
|
lie "3.1.1"
|
||||||
|
|
||||||
|
md5-node@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/md5-node/-/md5-node-1.0.1.tgz#0e22d009d46bdc95b1d3c5e8c8feddc1a5c3aa88"
|
||||||
|
integrity sha1-DiLQCdRr3JWx08XoyP7dwaXDqog=
|
||||||
|
|
||||||
media-typer@0.3.0:
|
media-typer@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
@ -319,6 +331,14 @@ ms@2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||||
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||||
|
|
||||||
|
nedb@0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/nedb/-/nedb-0.0.6.tgz#a2e6c02cb2fcacf91245b02431f44cf1664aa85f"
|
||||||
|
integrity sha1-oubALLL8rPkSRbAkMfRM8WZKqF8=
|
||||||
|
dependencies:
|
||||||
|
async "~0.2.8"
|
||||||
|
underscore "~1.4.4"
|
||||||
|
|
||||||
nedb@^1.8.0:
|
nedb@^1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/nedb/-/nedb-1.8.0.tgz#0e3502cd82c004d5355a43c9e55577bd7bd91d88"
|
resolved "https://registry.yarnpkg.com/nedb/-/nedb-1.8.0.tgz#0e3502cd82c004d5355a43c9e55577bd7bd91d88"
|
||||||
@ -444,6 +464,11 @@ setprototypeof@1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||||
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
||||||
|
|
||||||
|
string-random@^0.1.3:
|
||||||
|
version "0.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-random/-/string-random-0.1.3.tgz#083f39835c2430fe0be76b9e72f0736e2e0f7b74"
|
||||||
|
integrity sha512-g+UsIwzKhNi+9/+Q3Q7hP8R4HkQxiIkQlttnxw6GRdk9pnnkGIv53C6H8dvh8wxAVDhkqpnWeauaPXS1b2sBJg==
|
||||||
|
|
||||||
toidentifier@1.0.0:
|
toidentifier@1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
|
Loading…
Reference in New Issue
Block a user