2021-11-28 22:50:56 +08:00
|
|
|
import nedb from 'nedb'
|
2022-09-25 00:11:49 +08:00
|
|
|
import express from 'express'
|
2021-11-28 22:50:56 +08:00
|
|
|
import expressWs from 'express-ws'
|
|
|
|
import session from 'express-session'
|
|
|
|
import sessionDb from 'express-session-nedb'
|
|
|
|
import random from 'string-random'
|
2021-07-25 17:09:08 +08:00
|
|
|
import formidable from 'formidable'
|
2021-11-28 22:50:56 +08:00
|
|
|
import md5 from 'md5-node'
|
2021-12-14 05:28:42 +08:00
|
|
|
import HUB from './fmhub.js'
|
2021-07-26 11:22:48 +08:00
|
|
|
|
2022-09-25 00:11:49 +08:00
|
|
|
|
2021-08-26 19:52:40 +08:00
|
|
|
const databases = new Map() // 所有数据库
|
2021-12-14 05:28:42 +08:00
|
|
|
const FM = new HUB() // 频道消息分发器
|
2022-02-08 03:57:24 +08:00
|
|
|
const messagelist = new Map() // 消息队列的nedb存储
|
2021-07-25 17:09:08 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
const db = (name) => (databases.get(name) || function () {
|
|
|
|
let database = new nedb({ filename: `./data/db/${name}.db`, autoload: true, timestampData: true })
|
2021-07-25 17:09:08 +08:00
|
|
|
databases.set(name, database)
|
|
|
|
return database
|
|
|
|
}())
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
const session_store = sessionDb(session, db('session'))
|
2021-07-26 11:22:48 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 登录验证
|
|
|
|
const online = function (req, res, next) {
|
2021-08-26 19:52:40 +08:00
|
|
|
if (!req.session.account) return res.status(401).send('未登录')
|
2022-02-02 20:13:16 +08:00
|
|
|
if (req.session.account.gid !== 1) req.params.uid = req.session.account.uid
|
2021-07-26 13:17:39 +08:00
|
|
|
next()
|
2021-07-26 11:22:48 +08:00
|
|
|
}
|
|
|
|
|
2022-02-02 20:13:16 +08:00
|
|
|
// 权限(合并优化)
|
|
|
|
const admin = function (account, item) {
|
|
|
|
return (account.gid === 1 || account.uid === item.uid)
|
|
|
|
}
|
|
|
|
|
2021-07-26 19:12:47 +08:00
|
|
|
// 列表计量
|
2021-08-26 19:52:40 +08:00
|
|
|
const count_load = async (name, query) => await new Promise(resolve => db(name).count(query, (err, count) => resolve(count)))
|
2021-07-26 11:22:48 +08:00
|
|
|
|
2021-07-26 19:12:47 +08:00
|
|
|
// 条件查询
|
2021-11-28 22:50:56 +08:00
|
|
|
const list_load = async (name, query) => await new Promise(resolve => db(name).find(query, function (err, docs) {
|
|
|
|
return resolve(docs.Map((item, index) => Object.assign({}, { _id: item.id })))
|
2021-08-26 19:52:40 +08:00
|
|
|
}))
|
2021-07-26 16:19:48 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
const user_load = async (_id) => await new Promise(resolve => db('user').findOne({ _id }, function (err, doc) {
|
2021-08-26 19:52:40 +08:00
|
|
|
if (!doc) return resolve(doc)
|
2022-01-31 13:06:12 +08:00
|
|
|
// let { salt, password, mobile, email, ...user } = doc
|
|
|
|
// 这里只应提取有限简略信息附给列表, 因为个人信息中可能含有大量私有字段
|
2022-02-08 03:57:24 +08:00
|
|
|
// 但是..nedb 全在内存, 效率略略略...
|
2022-01-31 13:06:12 +08:00
|
|
|
let { _id, gid, name, avatar } = doc
|
|
|
|
return resolve({ _id, gid, name, avatar })
|
2021-08-26 19:52:40 +08:00
|
|
|
}))
|
2021-07-26 16:19:48 +08:00
|
|
|
|
2022-02-10 13:28:40 +08:00
|
|
|
// 通讯频道 Frequency Modulation, 游客使用公共账户 uid = 0
|
2021-11-30 22:33:17 +08:00
|
|
|
function websocketer(ws, req) {
|
2021-12-14 03:49:35 +08:00
|
|
|
let uid = req.session?.account?.uid || "0"
|
|
|
|
console.log(`用户 ${uid} 连接了服务器`)
|
|
|
|
|
2021-12-04 04:57:06 +08:00
|
|
|
FM.增加会话(uid, ws)
|
2021-11-30 22:09:07 +08:00
|
|
|
|
|
|
|
ws.on('message', function (msg) {
|
2021-12-14 06:26:18 +08:00
|
|
|
if (typeof (msg) !== "string") return console.log("消息不是字符串")
|
2022-02-11 15:58:57 +08:00
|
|
|
let { fm, data } = JSON.parse(msg) // 消息不是JSON
|
2021-12-04 04:57:06 +08:00
|
|
|
FM.发送消息(fm, uid, data)
|
2021-11-30 22:09:07 +08:00
|
|
|
})
|
2022-02-10 13:28:40 +08:00
|
|
|
ws.on('close', (code) => FM.移除会话(uid, ws))
|
|
|
|
ws.on('error', (code) => console.log('link error: ', code))
|
2021-11-30 22:09:07 +08:00
|
|
|
}
|
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 会话列表
|
|
|
|
function session_list(req, res) {
|
|
|
|
return session_store.db.find({ "data.account.uid": req.session.account.uid }, function (err, docs) {
|
|
|
|
return err ? res.status(500).send('错误') : res.json(docs)
|
|
|
|
})
|
2021-09-30 05:37:29 +08:00
|
|
|
}
|
|
|
|
|
2024-04-16 15:39:43 +08:00
|
|
|
import Cache from './src/cache.js'
|
2022-09-25 09:53:34 +08:00
|
|
|
const cache = new Cache()
|
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 登录会话
|
|
|
|
function session_create(req, res) {
|
2022-09-25 09:53:34 +08:00
|
|
|
let { mobile, code, name, password } = req.body
|
|
|
|
|
|
|
|
// 也许使用验证码登录(临时验证码) && code !== '000000'
|
|
|
|
if (mobile && code) {
|
|
|
|
if (code !== cache.get(mobile)) return res.status(400).send('验证码错误')
|
|
|
|
return db('user').findOne({ mobile }, function (err, doc) {
|
|
|
|
if (!doc) return res.status(400).send('账户不存在')
|
|
|
|
return req.session.regenerate(function (err) {
|
|
|
|
req.session.account = { uid: doc._id, gid: doc.gid ?? 0 }
|
|
|
|
let { salt, password, ...user } = doc
|
|
|
|
return res.json(user)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2024-04-24 01:38:25 +08:00
|
|
|
|
2022-09-25 09:53:34 +08:00
|
|
|
// 也许使用账号密码登录
|
|
|
|
return db('user').findOne({ name }, function (err, doc) {
|
2021-11-29 00:24:09 +08:00
|
|
|
if (!doc) return res.status(400).send('账户不存在')
|
2022-09-25 09:53:34 +08:00
|
|
|
if (md5(password + doc.salt) !== doc.password) return res.status(400).send('密码错误')
|
2021-11-29 00:24:09 +08:00
|
|
|
return req.session.regenerate(function (err) {
|
|
|
|
req.session.account = { uid: doc._id, gid: doc.gid ?? 0 }
|
|
|
|
let { salt, password, ...user } = doc
|
|
|
|
return res.json(user)
|
|
|
|
})
|
2021-11-28 22:50:56 +08:00
|
|
|
})
|
2021-11-29 00:24:09 +08:00
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 注销会话 (当前会话)
|
|
|
|
function sessionDeleteSelf(req, res) {
|
2021-11-28 22:50:56 +08:00
|
|
|
return req.session.destroy(function (err) {
|
|
|
|
return res.status(err ? 500 : 200).send(err ? '错误' : '退出登录')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 注销会话 (指定会话)
|
|
|
|
function session_delete(req, res) {
|
|
|
|
return req.sessionStore.destroy(req.params.sid, function (err) {
|
|
|
|
return err ? res.status(500).send('错误') : res.send('退出登录')
|
|
|
|
})
|
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 账户资料 (当前账户)
|
|
|
|
function profile(req, res) {
|
2021-12-15 04:55:56 +08:00
|
|
|
if (!req.session.account) return res.json({ name: '游客', avatar: '', online: false })
|
2021-11-28 22:50:56 +08:00
|
|
|
return db('user').findOne({ _id: req.session.account.uid }, function (err, doc) {
|
2021-12-15 04:55:56 +08:00
|
|
|
if (err) return res.status(400).send('账户不存在')
|
|
|
|
doc.online = true
|
2021-11-28 22:50:56 +08:00
|
|
|
delete doc.salt
|
|
|
|
delete doc.password
|
|
|
|
return res.json(doc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 列表对象
|
|
|
|
const object_list = async function (req, res) {
|
2021-12-12 05:09:03 +08:00
|
|
|
let { pagesize, page, count, like, post, tid, top, uid, user, sort, desc, ...query } = req.query
|
2021-11-28 22:50:56 +08:00
|
|
|
|
|
|
|
if (tid) query.tid = Number(tid) // 某些查询参数需要转换类型
|
|
|
|
if (top) query.top = Number(top) // 某些查询参数需要转换类型
|
2021-11-08 08:12:33 +08:00
|
|
|
if (uid && uid !== req.session?.account?.uid) query.public = true // 如果查询条件限定为自己的, 则不用限制范围到公开的
|
|
|
|
|
2021-09-30 05:37:29 +08:00
|
|
|
page = Number(page) || 1 // 默认页码1
|
|
|
|
pagesize = Number(pagesize) || 20 // 默认分页20
|
|
|
|
let skip = (page - 1) * pagesize // 截取点
|
2021-11-08 08:12:33 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 登录状态时, 查询自己点赞过的和评论过的
|
2021-07-26 11:22:48 +08:00
|
|
|
if (req.session?.account?.uid) {
|
2021-11-28 22:50:56 +08:00
|
|
|
if (like) query.$or = await list_load('like', { attach: req.params.name, uid: req.session.account.uid })
|
|
|
|
if (post) query.$or = await list_load('post', { attach: req.params.name, uid: req.session.account.uid })
|
2021-09-30 05:37:29 +08:00
|
|
|
}
|
2021-07-26 11:22:48 +08:00
|
|
|
|
2021-11-29 00:24:09 +08:00
|
|
|
// 消息限定范围
|
|
|
|
if (req.params.name === 'message' && req.session.account.gid !== 1) {
|
|
|
|
if (query.to) query.to = req.session.account.uid // 只能查发给自己的消息
|
|
|
|
else query.uid = req.session.account.uid // 否则默认自己发出去的
|
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 要求附带统计信息
|
|
|
|
if (count) await new Promise(resolve => db(req.params.name).count(query, function (err, count) {
|
|
|
|
res.header('count', count)
|
|
|
|
res.header('page', page)
|
|
|
|
res.header('pages', Math.ceil(count / pagesize))
|
|
|
|
res.header('pagesize', pagesize)
|
|
|
|
resolve()
|
|
|
|
}))
|
|
|
|
|
2021-12-12 05:09:03 +08:00
|
|
|
desc = (desc === "1") ? 1 : -1
|
|
|
|
let is_sort = {}
|
|
|
|
switch (sort) {
|
|
|
|
case 'top': is_sort.top = desc; break;
|
|
|
|
case 'hot': is_sort.hot = desc; break;
|
|
|
|
case 'createdAt': is_sort.createdAt = desc; break;
|
|
|
|
case 'updatedAt': is_sort.updatedAt = desc; break;
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
|
|
|
return db(req.params.name).find(query).skip(skip).limit(pagesize).sort(sort).exec(async function (err, docs) {
|
2021-11-28 22:50:56 +08:00
|
|
|
return res.json(await Promise.all(docs.map(async item => {
|
|
|
|
item.posts = await count_load('post', { attach: req.params.name, aid: item._id }) // 附加评论数量
|
|
|
|
item.likes = await count_load('like', { attach: req.params.name, aid: item._id }) // 附加点赞数量
|
|
|
|
if (req.params.name === 'user') {
|
|
|
|
delete item.salt
|
|
|
|
delete item.password
|
|
|
|
delete item.mobile
|
|
|
|
delete item.email
|
2021-12-12 05:09:03 +08:00
|
|
|
} else {
|
2021-12-14 05:28:42 +08:00
|
|
|
item.user = await user_load(item.uid) // 附加用户信息(user对象没有作者)
|
2021-11-28 22:50:56 +08:00
|
|
|
}
|
2022-02-02 20:13:16 +08:00
|
|
|
if (req.params.name != 'user' && req.session.account) {
|
|
|
|
item.like = !!(await count_load('like', {
|
|
|
|
attach: req.params.name,
|
|
|
|
aid: item._id,
|
|
|
|
uid: req.session.account.uid
|
|
|
|
}))
|
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
return item
|
|
|
|
})))
|
2021-07-25 17:09:08 +08:00
|
|
|
})
|
2021-08-26 19:52:40 +08:00
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 创建对象
|
|
|
|
const object_create = async function (req, res) {
|
|
|
|
|
2024-04-24 02:04:08 +08:00
|
|
|
// 游客和普通用户禁止设置, 权限和计算属性
|
2021-08-26 19:52:40 +08:00
|
|
|
if (req.session?.account?.gid != 1) {
|
2024-04-24 02:04:08 +08:00
|
|
|
['_id', 'uid', 'top', 'user', 'createdAt', 'updatedAt', 'views', 'posts', 'likes', 'files'].forEach(i => delete req.body[i])
|
2021-08-26 19:52:40 +08:00
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
|
2024-04-24 02:04:08 +08:00
|
|
|
// 如果创建对象是用户作一些特殊处理, 否则创建对象作通用处理
|
2021-11-28 22:50:56 +08:00
|
|
|
if (req.params.name === 'user') {
|
2024-04-24 02:04:08 +08:00
|
|
|
const { name, password, avatar = '' } = req.body
|
|
|
|
if (!name) return res.status(400).send('用户名不能为空')
|
|
|
|
if (!password) return res.status(400).send('密码不能为空')
|
2024-04-24 03:10:18 +08:00
|
|
|
if (await count_load('user', { name })) return res.status(400).send('用户名已被占用')
|
2024-04-24 02:04:08 +08:00
|
|
|
req.body = {
|
|
|
|
...req.body, avatar,
|
|
|
|
gid: (await count_load('user', {})) ? 0 : 1, // 默认是管理员为首个注册用户
|
|
|
|
salt: random(32), // 密码加盐
|
|
|
|
password: md5(password + random(32)) // 必要设置密码
|
2021-12-01 04:38:42 +08:00
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
} else {
|
2021-12-01 04:38:42 +08:00
|
|
|
if (!req.session.account) return res.status(401).send('需要登录')
|
2024-04-24 02:04:08 +08:00
|
|
|
req.body = { ...req.body, uid: req.session.account.uid, public: true, views: 0 }
|
2021-08-26 19:52:40 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 02:04:08 +08:00
|
|
|
// 如果包含标签(先查询是否存在, 存在则使用返回的_id进行挂载, 不存在则创建新的)
|
2022-01-30 17:28:09 +08:00
|
|
|
if (req.body.tags && Array.isArray(req.body.tags)) {
|
|
|
|
req.body.tags.forEach(item => {
|
|
|
|
db('tag').findOne({ name: item }, function (err, doc) {
|
|
|
|
if (err && !doc) {
|
|
|
|
return // 创建新的
|
|
|
|
} else {
|
|
|
|
return // 使用这个 _id, 向它写入
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
// 是否可以创建一个复杂关系型数据库?
|
|
|
|
// 以应对映射的共同对象
|
|
|
|
// 例如在使用 tag 时, 向 idea 表的 tag 段读写, 即是 tag表的 idea 索引范围
|
|
|
|
// (自动构建和维护双向索引)
|
|
|
|
// 当删除此 idea 时, 也自动清理掉 tag 对 idea 的连接
|
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 如果是挂载对象到指定目标
|
|
|
|
if (req.body.attach && req.body.aid) {
|
|
|
|
let count = await count_load(req.body.attach, { _id: req.body.aid })
|
|
|
|
if (!count) return res.status(404).send('目标挂载对象不存在')
|
|
|
|
}
|
2021-07-25 17:09:08 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 写入对象
|
|
|
|
return db(req.params.name).insert(req.body, async function (err, doc) {
|
|
|
|
if (!doc) return res.status(500).send('创建失败')
|
2021-12-01 04:38:42 +08:00
|
|
|
if (req.params.name !== 'user') {
|
|
|
|
doc.user = await user_load(doc.uid)
|
|
|
|
} else {
|
|
|
|
delete doc.salt
|
|
|
|
delete doc.password
|
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
return res.json(doc)
|
2021-07-26 13:17:39 +08:00
|
|
|
})
|
2021-11-28 22:50:56 +08:00
|
|
|
}
|
2021-08-26 19:52:40 +08:00
|
|
|
|
2024-04-24 03:10:18 +08:00
|
|
|
const 密码加密 = (password, salt = random(32)) => ({ salt, password: md5(password + salt) })
|
|
|
|
const 密码解密 = (password, salt) => md5(password + salt)
|
|
|
|
|
2022-01-30 17:28:09 +08:00
|
|
|
// 修改对象
|
2022-02-02 20:13:16 +08:00
|
|
|
function object_patch(req, res, next) {
|
2024-04-24 03:10:18 +08:00
|
|
|
return db(req.params.name).findOne({ _id: req.params._id }, async function (err, doc) {
|
2022-01-30 17:28:09 +08:00
|
|
|
if (!doc) return res.status(404).send('目标对象不存在')
|
2022-02-08 04:39:51 +08:00
|
|
|
if (typeof (req.body.attach) !== "undefined") return res.status(403).send("无权限修改挂载目标")
|
|
|
|
if (typeof (req.body.aid) !== "undefined") return res.status(403).send("无权限修改挂载目标")
|
|
|
|
|
2022-01-30 17:28:09 +08:00
|
|
|
// 如果是 user 做一些特殊处理
|
|
|
|
if (req.params.name === 'user') {
|
2022-02-02 20:13:16 +08:00
|
|
|
if (req.session.account.gid !== 1) {
|
2024-04-24 03:10:18 +08:00
|
|
|
if (req.session.account.uid !== doc._id) return res.status(403).send('没有权限修改账户')
|
|
|
|
if (typeOf(req.body.gid) == "undefined") return res.status(403).send('没有权限修改权限')
|
2022-01-30 17:28:09 +08:00
|
|
|
}
|
|
|
|
if (req.body.password) {
|
2024-04-24 03:10:18 +08:00
|
|
|
req.body = { ...req.body, ...密码加密(req.body.password) }
|
2022-01-30 17:28:09 +08:00
|
|
|
}
|
2024-04-24 03:10:18 +08:00
|
|
|
if (req.body.name && await count_load('user', { name: req.body.name })) return res.status(400).send('用户名已被占用')
|
2022-01-30 17:28:09 +08:00
|
|
|
} else {
|
2024-04-24 03:10:18 +08:00
|
|
|
if (req.session.account.uid !== doc.uid && req.session.account.gid !== 1) return res.status(403).send('没有权限修改对象')
|
|
|
|
if (req.body.uid && req.session.account.gid !== 1) return res.status(403).send('没有权限修改归属')
|
2022-01-30 17:28:09 +08:00
|
|
|
}
|
|
|
|
return db(req.params.name).update({ _id: req.params._id }, { $set: req.body }, function (err, count) {
|
|
|
|
if (!count) return res.status(500).send('修改失败')
|
2022-02-10 13:28:40 +08:00
|
|
|
res.send('修改成功')
|
|
|
|
// 会话完全成功后执行
|
2022-01-30 17:28:09 +08:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 删除对象
|
|
|
|
const object_remove = function (req, res) {
|
|
|
|
return db(req.params.name).findOne({ _id: req.params._id }, async function (err, doc) {
|
2021-12-14 23:02:06 +08:00
|
|
|
if (!doc) return res.status(404).send('目标对象不存在')
|
2021-08-26 19:52:40 +08:00
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 如果是删除用户作一些特殊处理
|
|
|
|
if (req.params.name === 'user') {
|
|
|
|
if (req.session.account.gid !== 1 && req.session.account.uid !== doc._id) {
|
|
|
|
return res.status(400).send('没有权限删除此账户')
|
|
|
|
}
|
|
|
|
if (await count_load('account', { _id: req.params.id, gid: 1 }) === 1) {
|
|
|
|
return res.status(400).send('不可以删除唯一的管理员账户')
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (req.session.account.gid !== 1 && req.session.account.uid !== doc.uid) {
|
|
|
|
return res.status(403).send('没有权限删除此对象')
|
|
|
|
}
|
2021-07-25 17:09:08 +08:00
|
|
|
}
|
2021-11-28 22:50:56 +08:00
|
|
|
|
2021-12-14 05:28:42 +08:00
|
|
|
// TODO: 处理掉一些附属对象
|
2022-02-02 20:13:16 +08:00
|
|
|
// 似乎要遍历所有对象类型?
|
2021-11-28 22:50:56 +08:00
|
|
|
|
|
|
|
return db(req.params.name).remove({ _id: req.params._id }, function (err, count) {
|
|
|
|
return count ? res.send('删除成功') : res.status(403).send('删除失败')
|
|
|
|
// TODO: 当对象被删除时通过此连接通知所有在线终端
|
|
|
|
})
|
2021-07-25 17:09:08 +08:00
|
|
|
})
|
2021-08-26 19:52:40 +08:00
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 读取对象
|
|
|
|
const object_load = function (req, res) {
|
|
|
|
return db(req.params.name).findOne({ _id: req.params._id }, async function (err, doc) {
|
2024-04-24 02:04:08 +08:00
|
|
|
if (!doc) return res.status(404).send('目标资源不存在')
|
|
|
|
if (!doc.public && doc.uid !== session?.account?.uid) return res.status(403).send('没有权限读取')
|
|
|
|
if (req.params.name === 'user') ['salt', 'password', 'mobile', 'email'].forEach(field => delete doc[field])
|
|
|
|
else doc.user = await user_load(doc.uid)
|
|
|
|
db(req.params.name).update({ _id: req.params._id }, { $set: { views: (doc.views || 0) + 1 } })
|
2021-12-12 05:09:03 +08:00
|
|
|
return res.json(doc)
|
2021-07-26 13:17:39 +08:00
|
|
|
})
|
2021-08-26 19:52:40 +08:00
|
|
|
}
|
|
|
|
|
2021-11-28 22:50:56 +08:00
|
|
|
// 附件上传
|
|
|
|
const file_upload = function (req, res) {
|
|
|
|
return db(req.params.name).findOne({ _id: req.params._id }, function (err, doc) {
|
|
|
|
if (!doc) return res.status(404).send('目标对象不存在')
|
|
|
|
if (req.session.account.uid !== doc.uid && req.session.account.gid !== 1) {
|
|
|
|
return res.status(403).send('没有权限上传')
|
|
|
|
}
|
|
|
|
return formidable({ multiples: true, uploadDir: 'data/file', keepExtensions: true, maxFieldsSize: 200 * 1024 * 1024 }).parse(req, function (err, fields, files) {
|
2024-04-24 01:38:25 +08:00
|
|
|
const list = Object.values(files).map(item => Array.isArray(item) ? item : [item]).flat().map(({ filepath, mimetype, mtime, newFilename, originalFilename, size }) => {
|
|
|
|
return { filepath, mimetype, mtime, newFilename, originalFilename, size }
|
|
|
|
})
|
2021-11-28 22:50:56 +08:00
|
|
|
return db(req.params.name).update({ _id: req.params._id }, { $addToSet: { file: { $each: list } } }, function (err, count) {
|
|
|
|
if (!count) return res.status(500).send('附件挂载对象失败')
|
|
|
|
console.log(list)
|
|
|
|
return res.json(list)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2021-09-30 05:37:29 +08:00
|
|
|
|
2022-02-19 05:58:58 +08:00
|
|
|
// 向账户上传文件 (头像, 背景, 其它文件)
|
|
|
|
const uploadfile = function (req, res) {
|
2022-01-30 17:28:09 +08:00
|
|
|
|
|
|
|
let idable = formidable({
|
|
|
|
multiples: true,
|
|
|
|
uploadDir: 'data/file',
|
|
|
|
keepExtensions: true,
|
|
|
|
maxFieldsSize: 200 * 1024 * 1024,
|
|
|
|
})
|
|
|
|
|
|
|
|
idable.parse(req, (err, fields, files) => {
|
2022-02-19 05:58:58 +08:00
|
|
|
let query = { _id: req.session.account.uid }
|
2022-01-30 17:28:09 +08:00
|
|
|
|
2022-02-19 05:58:58 +08:00
|
|
|
// 针对特定对象处理上传字段(头像)
|
|
|
|
let avatar = files["avatar"]
|
|
|
|
if (avatar) {
|
|
|
|
let list = (Array.isArray(avatar) ? avatar : [avatar])
|
|
|
|
db('user').update(query, {
|
|
|
|
$addToSet: { file: { $each: list } }, // 保存记录
|
|
|
|
$set: { avatar: '/data/file/' + list[0].newFilename }, // 替换头像
|
2022-01-30 17:28:09 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-02-19 05:58:58 +08:00
|
|
|
// 针对特定对象处理上传字段(背景图)
|
|
|
|
let background = files["background"]
|
|
|
|
if (background) {
|
|
|
|
let list = (Array.isArray(background) ? background : [background])
|
|
|
|
db('user').update(query, {
|
|
|
|
$addToSet: { file: { $each: list } }, // 保存记录
|
|
|
|
$set: { background: '/data/file/' + list[0].newFilename }, // 替换背景
|
|
|
|
})
|
2022-01-30 17:28:09 +08:00
|
|
|
}
|
2024-04-24 02:04:08 +08:00
|
|
|
|
2022-02-19 05:58:58 +08:00
|
|
|
res.json(files)
|
2022-01-30 17:28:09 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-12 05:09:03 +08:00
|
|
|
const db_compact = function (req, res) {
|
|
|
|
db(req.params.name).persistence.compactDatafile()
|
|
|
|
return res.send("ok")
|
|
|
|
}
|
|
|
|
|
2022-02-08 03:57:24 +08:00
|
|
|
// 读取对象列表
|
|
|
|
function index_get(req, res) {
|
|
|
|
// 返回对象列表
|
|
|
|
let list = []
|
|
|
|
databases.forEach((value, key) => {
|
|
|
|
list.push(key)
|
|
|
|
})
|
|
|
|
res.json(list)
|
|
|
|
}
|
|
|
|
|
2022-01-30 17:28:09 +08:00
|
|
|
const app = expressWs(express()).app
|
2021-08-26 19:52:40 +08:00
|
|
|
app.use(express.json())
|
|
|
|
app.use(express.urlencoded({ extended: false }))
|
2021-11-29 13:56:49 +08:00
|
|
|
app.use(session({ secret: 'kana', name: 'sid', resave: false, saveUninitialized: false, cookie: { maxAge: 180 * 24 * 3600000 }, store: session_store }))
|
2024-04-29 20:41:31 +08:00
|
|
|
app.use('/api/data/file/', express.static('data/file'))
|
|
|
|
app.ws('/api', websocketer)
|
|
|
|
app.route('/api/').get(index_get)
|
|
|
|
app.route('/api/account').get(profile).post(online, uploadfile)
|
|
|
|
app.route('/api/session').get(online, session_list).post(session_create).delete(online, sessionDeleteSelf)
|
|
|
|
app.route('/api/session/:sid').delete(online, session_delete)
|
|
|
|
app.route('/api/:name').get(object_list).post(object_create).put(db_compact)
|
|
|
|
app.route('/api/:name/:_id').get(object_load).post(online, file_upload).put().patch(online, object_patch).delete(online, object_remove)
|
2021-07-25 17:09:08 +08:00
|
|
|
app.listen(2333)
|