使用pg数据库重构

This commit is contained in:
2025-02-16 23:08:25 +08:00
parent 0b67c146a8
commit a3c122e76b
39 changed files with 306 additions and 681 deletions

View File

@@ -1,15 +1,15 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import MountUserAgent from "../Plugs/Middleware/MountUserAgent";
import axios from "axios";
import MountIP from "../Plugs/Middleware/MountIP";
import CheckCaptchaPassed from "../Plugs/Middleware/CheckCaptchaPassed";
import { BlogComment as BlogCommentType } from "@/Types/Schema"
// 提交博客评论
class BlogComment extends API {
constructor() {
super('POST', '/blogComment', CheckCaptchaPassed, MountUserAgent, MountIP);
super('POST', '/blogComment', MountUserAgent, MountIP);
}
public async onRequset(data: any, res: any) {
@@ -26,17 +26,17 @@ class BlogComment extends API {
// 获取IPAddress
let ip_address = '未知'
try {
let ipAddressRes = await axios.get(`https://mesh.if.iqiyi.com/aid/ip/info?version=1.1.1&ip=`+_ip);
let ipAddressRes = await axios.get(`https://mesh.if.iqiyi.com/aid/ip/info?version=1.1.1&ip=` + _ip);
if (ipAddressRes.data && ipAddressRes.data.msg == 'success') {
ip_address = ipAddressRes.data.data.countryCN == '中国' ? ipAddressRes.data.data.provinceCN : ipAddressRes.data.data.countryCN;
}
} catch (error) {
this.logger.warn('获取IP属地失败', error);
}
let blogLikeRes = await MySQLConnection.execute('INSERT INTO blog_comment (uuid, content, name, ip, ip_address, user_agent, time) VALUES (?,?,?,?,?,?,?)', [bloguuid, content.trim(), name.trim(), _ip, ip_address, _userAgent, Date.now()]);
if (!blogLikeRes || blogLikeRes.affectedRows != 1) {
let blogLikeRes = await Database.query<BlogCommentType>('INSERT INTO blog_comment (uuid, content, name, ip, ip_address, user_agent, display, created_at) VALUES ($1,$2,$3,$4,$5,$6,true,$7)', [bloguuid, content.trim(), name.trim(), _ip, ip_address, _userAgent, new Date()]);
if (!blogLikeRes) {
this.logger.error('发布博客评论时,数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
}

View File

@@ -1,8 +1,9 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import { Buffer } from 'buffer';
import axios from "axios";
import { Blog } from "@/Types/Schema";
// 点赞
@@ -18,15 +19,11 @@ class BlogLike extends API {
return res.json(ServerStdResponse.INVALID_PARAMS);
}
let blogLikeRes = await MySQLConnection.execute('UPDATE blog SET like_count = like_count + 1 WHERE access_level > ? AND uuid = ? ', [this.defaultAccessLevel, bloguuid]);
let blogLikeRes = await Database.query<Blog>('UPDATE blog SET like_count = like_count + 1 WHERE access_level > $1 AND uuid = $2 ', [this.defaultAccessLevel, bloguuid]);
if (!blogLikeRes) {
this.logger.error('点赞博客时,数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
}
if (blogLikeRes.affectedRows != 1) {
this.logger.warn('查询的博客不存在或不可见', bloguuid);
return res.json(ServerStdResponse.BLOG.NOTFOUND);
}
return res.json(ServerStdResponse.OK);
}
}

View File

@@ -1,41 +0,0 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import captchaSession from "../Plugs/Service/captchaSession";
// 检查人机验证
class CheckCaptcha extends API {
constructor() {
super('POST', '/checkCaptcha');
}
public async onRequset(data: any, res: any) {
let { session, rotateDeg } = data;
if (!session || !rotateDeg) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
switch (await captchaSession.check(session, rotateDeg)) {
case 0:
// 验证码已过期或服务器错误
res.json(ServerStdResponse.CAPTCHA.NOTFOUND);
break;
case 1:
// 验证通过
res.json(ServerStdResponse.OK);
break;
case -1:
// 超过最大尝试次数
res.json(ServerStdResponse.CAPTCHA.MAX_TRY_COUNT);
break;
case -2:
// 角度不正确
res.json(ServerStdResponse.CAPTCHA.NOTRIGHT);
break;
default:
// 未知错误
res.json(ServerStdResponse.SERVER_ERROR);
break;
}
}
}
export default CheckCaptcha;

View File

@@ -1,6 +1,6 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
// 删除博客
@@ -10,13 +10,13 @@ class DelBlog extends API {
}
public async onRequset(data: any, res: any) {
let { id } = data;
if (!id) {
let { uuid } = data;
if (!uuid) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
let execRes = await MySQLConnection.execute('DELETE FROM blog WHERE `id` = ?', [id]);
let execRes = await Database.query('DELETE FROM blog WHERE uuid = $1', [uuid]);
if (!execRes || execRes.affectedRows != 1) {
if (!execRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({ ...ServerStdResponse.OK });

View File

@@ -1,6 +1,6 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
// 删除资源
@@ -10,13 +10,13 @@ class DelResource extends API {
}
public async onRequset(data: any, res: any) {
let { id } = data;
if (!id) {
let { uuid } = data;
if (!uuid) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
let execRes = await MySQLConnection.execute('DELETE FROM resource WHERE `id` = ?', [id]);
let execRes = await Database.query('DELETE FROM resource WHERE uuid = $1', [uuid]);
if (!execRes || execRes.affectedRows != 1) {
if (!execRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({ ...ServerStdResponse.OK });

View File

@@ -1,7 +1,8 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import { Blog } from "@/Types/Schema";
// 获取博客列表
class GetBlogs extends API {
@@ -10,8 +11,7 @@ class GetBlogs extends API {
}
public async onRequset(data: any, res: any) {
// const { uuid } = data._jwt;
let resourcesRes = await MySQLConnection.execute("SELECT * FROM blog ORDER BY id DESC");
let resourcesRes = await Database.query<Blog>("SELECT * FROM blog ORDER BY created_at DESC");
if (!resourcesRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}

View File

@@ -1,6 +1,6 @@
import { API, RequestData } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import jwt from "jsonwebtoken";
import config from "../../config";

View File

@@ -1,7 +1,8 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import { Resource } from "@/Types/Schema";
// 获取资源列表
class GetResources extends API {
@@ -11,7 +12,7 @@ class GetResources extends API {
public async onRequset(data: any, res: any) {
// const { uuid } = data._jwt;
let resourcesRes = await MySQLConnection.execute("SELECT * FROM resource");
let resourcesRes = await Database.query<Resource>("SELECT * FROM resource ORDER BY type, recommand, created_at DESC");
if (!resourcesRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}

View File

@@ -1,17 +1,17 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import MountUserAgent from "../../Plugs/Middleware/MountUserAgent";
import MountIP from "../../Plugs/Middleware/MountIP";
import CheckCaptchaPassed from "../../Plugs/Middleware/CheckCaptchaPassed";
import config from "../../config";
import jwt from 'jsonwebtoken'
import crypto from 'crypto'
import { User } from "@/Types/Schema";
// 登录
class Login extends API {
constructor() {
super('POST', '/console/login', CheckCaptchaPassed, MountUserAgent, MountIP);
super('POST', '/console/login', MountUserAgent, MountIP);
}
public async onRequset(data: any, res: any) {
@@ -21,28 +21,28 @@ class Login extends API {
}
// 检查用户是否存在
let userInfoRes = await MySQLConnection.execute('SELECT * FROM user WHERE username = ?', [username]);
if(!userInfoRes){
let userInfoRes = await Database.query<User>('SELECT * FROM user WHERE username = $1', [username]);
if (!userInfoRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}
if (userInfoRes.length != 1) {
return res.json(ServerStdResponse.USER.NOTFOUND);
}
userInfoRes = userInfoRes[0];
const UserInfo = userInfoRes[0];
// 检查密码是否正确
if(crypto.createHash('sha256').update(`${userInfoRes.salt}${password}`).digest('hex') != userInfoRes.password){
if (crypto.createHash('sha256').update(`${UserInfo.salt}${password}`).digest('hex') != UserInfo.password) {
return res.json(ServerStdResponse.USER.PASSWORD_ERROR);
}
// 准备jwtToken
const jwtPayload = {
uuid: userInfoRes.uuid,
uuid: UserInfo.uuid,
loginTime: Date.now()
}
let jwtToken = jwt.sign(jwtPayload, config.jwt.secret, { expiresIn: config.jwt.expiresIn });
// 写入登录日志
MySQLConnection.execute('INSERT INTO user_login_log (user_uuid, ip, user_agent, time) VALUES (?,?,?,?)', [userInfoRes.uuid, _ip, _userAgent, Date.now()]);
Database.query('INSERT INTO user_login_log (user_uuid, ip, user_agent, time) VALUES ($1,$2,$3,$4)', [UserInfo.uuid, _ip, _userAgent, Date.now()]);
return res.json({ ...ServerStdResponse.OK, data: { token: jwtToken } });
}
}

View File

@@ -1,8 +1,9 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import crypto from 'crypto'
import { Blog } from "@/Types/Schema";
// 保存博客
class SaveBlog extends API {
@@ -11,21 +12,21 @@ class SaveBlog extends API {
}
public async onRequset(data: any, res: any) {
let { id, uuid, title, description, publish_time, src, access_level } = data;
if (!title || !description || !publish_time || !src || !access_level) {
let { uuid, title, description, created_at, src, access_level } = data;
if (!title || !description || !created_at || !src || !access_level) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
let execRes: any;
if (id) {
if (uuid) {
// 保存
execRes = await MySQLConnection.execute('UPDATE blog SET title = ?, description = ?, publish_time = ?, src = ?, access_level = ? WHERE `id` = ?', [title, description, publish_time, src, access_level, id]);
execRes = await Database.query<Blog>('UPDATE blog SET title = $1, description = $2, created_at = $3, src = $4, access_level = $5 WHERE uuid = $6', [title, description, created_at, src, access_level, uuid]);
} else {
// 新建
const uuid = crypto.createHash('md5').update(`${Math.random()}${Date.now()}`).digest('hex');
execRes = await MySQLConnection.execute('INSERT INTO blog (uuid, title, description, src, publish_time, access_level, visit_count, like_count) VALUES (?,?,?,?,?,?,?,?)', [uuid, title, description, src, publish_time, access_level, 0, 0]);
execRes = await Database.query<Blog>('INSERT INTO blog (uuid, title, description, src, created_at, access_level, visit_count, like_count) VALUES ($1,$2,$3,$4,$5,$6,$7,$8)', [uuid, title, description, src, created_at, access_level, 0, 0]);
}
if (!execRes || execRes.affectedRows != 1) {
if (!execRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({ ...ServerStdResponse.OK });

View File

@@ -1,7 +1,9 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import { Resource } from "@/Types/Schema";
import Crypto from 'crypto'
// 保存资源
class SaveResource extends API {
@@ -10,20 +12,21 @@ class SaveResource extends API {
}
public async onRequset(data: any, res: any) {
let { id, type, recommand, title, describe, icon_src, addition, src } = data;
let { uuid, type, recommand, title, describe, icon_src, addition, src } = data;
if (!type || !recommand || !title || !describe || !icon_src || !addition || !src) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
let execRes: any;
if (id) {
if (uuid) {
// 保存
execRes = await MySQLConnection.execute('UPDATE resource SET `type` = ?, `recommand` = ?, `title` = ?, `describe` = ?, `addition` = ?, `icon_src` = ?, `src` = ? WHERE `id` = ?', [type, recommand, title, describe, addition, icon_src, src, id]);
execRes = await Database.query<Resource>('UPDATE resource SET "type" = $1, "recommand" = $2, "title" = $3, "describe" = $4, "addition" = $5, "icon_src" = $6, "src" = $7 WHERE "uuid" = $8', [type, recommand, title, describe, addition, icon_src, src, uuid]);
} else {
// 新建
execRes = await MySQLConnection.execute('INSERT INTO resource (`type`, `recommand`, `title`, `describe`, `addition`, `icon_src`, `src`) VALUES (?,?,?,?,?,?,?)', [type, recommand, title, describe, addition, icon_src, src]);
uuid = Crypto.createHash('md5').update(`${Math.random()}${Date.now()}`).digest('hex');
execRes = await Database.query<Resource>('INSERT INTO resource ("uuid","type", "recommand", "title", "describe", "addition", "icon_src", "src", "created_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)', [uuid, type, recommand, title, describe, addition, icon_src, src, new Date()]);
}
if (!execRes || execRes.affectedRows != 1) {
if (!execRes) {
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({ ...ServerStdResponse.OK });

View File

@@ -1,8 +1,9 @@
import { API } from "../../Plugs/API/API";
import ServerStdResponse from "../../ServerStdResponse";
import MySQLConnection from '../../Plugs/MySQLConnection'
import Database from '../../Plugs/Database'
import Auth from "../../Plugs/Middleware/Auth";
import crypto from 'crypto'
import { Blog } from "@/Types/Schema";
// 设置博客密码
class SetBlogPasswd extends API {
@@ -16,7 +17,7 @@ class SetBlogPasswd extends API {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
const encrypt_p = crypto.createHash('sha256').update(passwd).digest('hex');
MySQLConnection.execute('UPDATE blog SET encrypt_p = ? WHERE uuid = ?', [encrypt_p, uuid]);
Database.query<Blog>('UPDATE blog SET encrypt_p = $1 WHERE uuid = $2', [encrypt_p, uuid]);
return res.json({ ...ServerStdResponse.OK });
}
}

View File

@@ -1,6 +1,7 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import { BlogComment } from "@/Types/Schema";
// 获取博客评论
class GetBlogComment extends API {
@@ -16,7 +17,7 @@ class GetBlogComment extends API {
return res.json(ServerStdResponse.INVALID_PARAMS);
}
let blogCommentRes = await MySQLConnection.execute('SELECT content, name, ip_address, time FROM blog_comment WHERE uuid = ? AND display = 1 ORDER BY time DESC LIMIT ? OFFSET ?;', [bloguuid, this.pageSize, (page - 1) * this.pageSize]);
let blogCommentRes = await Database.query<BlogComment>('SELECT content, name, ip_address, created_at FROM blog_comment WHERE uuid = $1 AND display = true ORDER BY created_at DESC LIMIT $2 OFFSET $3;', [bloguuid, this.pageSize, (page - 1) * this.pageSize]);
if (!blogCommentRes) {
this.logger.error('获取博客评论时,数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);

View File

@@ -1,10 +1,11 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import { Buffer } from 'buffer';
import axios from "axios";
import crypto from 'crypto'
import MountIP from "../Plugs/Middleware/MountIP";
import { Blog } from "@/Types/Schema";
// 获取博客内容
class GetBlogContent extends API {
@@ -22,14 +23,14 @@ class GetBlogContent extends API {
return res.json(ServerStdResponse.INVALID_PARAMS);
}
let blogContentRes = await MySQLConnection.execute(`SELECT * from blog WHERE access_level in (${this.AccessLevelRule.allow.join(',')}) AND uuid = ? `, [bloguuid]);
let blogContentRes = await Database.query<Blog>(`SELECT * from blog WHERE access_level in (${this.AccessLevelRule.allow.join(',')}) AND uuid = $1 `, [bloguuid]);
if (!blogContentRes) {
this.logger.error('查询时数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
}
if (blogContentRes.length == 0) {
// 公开范围不可见,查询允许无连接加密查看的数据
blogContentRes = await MySQLConnection.execute(`SELECT * from blog WHERE access_level in (${this.AccessLevelRule.encrypt_allow.join(',')}) AND uuid = ? `, [bloguuid]);
blogContentRes = await Database.query<Blog>(`SELECT * from blog WHERE access_level in (${this.AccessLevelRule.encrypt_allow.join(',')}) AND uuid = $1 `, [bloguuid]);
if (!blogContentRes) {
this.logger.error('查询时数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
@@ -57,14 +58,14 @@ class GetBlogContent extends API {
const base64Content = Buffer.from(response.data, 'utf-8').toString('base64');
// 访问次数+1
MySQLConnection.execute('UPDATE blog SET visit_count = visit_count + 1 WHERE uuid = ?', [bloguuid]);
Database.query('UPDATE blog SET visit_count = visit_count + 1 WHERE uuid = $1', [bloguuid]);
return res.json({
...ServerStdResponse.OK, data: {
data: base64Content,
info: {
title: blogContentRes[0].title,
description: blogContentRes[0].description,
publish_time: blogContentRes[0].publish_time,
publish_time: blogContentRes[0].created_at,
visit_count: blogContentRes[0].visit_count,
like_count: blogContentRes[0].like_count
}

View File

@@ -1,6 +1,7 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import { Blog } from "@/Types/Schema";
// 获取博客列表
class GetBlogList extends API {
@@ -10,12 +11,12 @@ class GetBlogList extends API {
private defaultAccessLevel = 9;
public async onRequset(data: any, res: any) {
let blogListRes = await MySQLConnection.execute('SELECT uuid, title, description, publish_time, access_level, visit_count, like_count from blog WHERE access_level >= ? ORDER BY publish_time DESC',[this.defaultAccessLevel]);
if(!blogListRes){
let blogListRes = await Database.query<Blog>('SELECT uuid, title, description, created_at, access_level, visit_count, like_count from blog WHERE access_level >= $1 ORDER BY created_at DESC', [this.defaultAccessLevel]);
if (!blogListRes) {
this.logger.error('查询时数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({...ServerStdResponse.OK, data: blogListRes});
return res.json({ ...ServerStdResponse.OK, data: blogListRes });
}
}

View File

@@ -1,36 +0,0 @@
import fs from "fs";
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import captchaSession from "../Plugs/Service/captchaSession";
import path from "path";
import sharp from "sharp";
import crypto from 'crypto'
// 获取人机验证图片及标识符
class GetCaptcha extends API {
constructor() {
super('GET', '/captcha');
}
public async onRequset(data: any, res: any) {
const imgsPath = path.join(__dirname, '../assets/captchaImgs');
const fileList = fs.readdirSync(imgsPath)
const imgPath = path.join(imgsPath, fileList[Math.floor(Math.random() * fileList.length)]);
const rotateDeg = Math.floor(Math.random() * 240) + 60;
const img = Buffer.from(await sharp(imgPath).rotate(-rotateDeg).toBuffer()).toString('base64')
const session = crypto.createHash('md5').update(`${Math.random()} ${Date.now()}`).digest('hex');
if (await captchaSession.add(session, rotateDeg)) {
return res.json({
...ServerStdResponse.OK, data: {
img: img,
session: session,
imgPreStr: 'data:image/jpeg;base64,'
}
});
} else {
return res.json(ServerStdResponse.SERVER_ERROR)
}
}
}
export default GetCaptcha;

View File

@@ -1,6 +1,7 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
import Database from '../Plugs/Database'
import { Resource } from "@/Types/Schema";
// 获取资源列表
class GetResourceList extends API {
@@ -11,18 +12,18 @@ class GetResourceList extends API {
public async onRequset(data: any, res: any) {
let { type } = data;
if(!type){
if (!type) {
return res.json(ServerStdResponse.PARAMS_MISSING);
}
if(!this.typeList.includes(type)){
if (!this.typeList.includes(type)) {
return res.json(ServerStdResponse.INVALID_PARAMS);
}
let resourceListRes = await MySQLConnection.execute('SELECT * from resource WHERE type = ? ORDER BY recommand ASC',[type]);
if(!resourceListRes){
let resourceListRes = await Database.query<Resource>('SELECT * from resource WHERE type = $1 ORDER BY recommand ASC', [type]);
if (!resourceListRes) {
this.logger.error('查询时数据库发生错误');
return res.json(ServerStdResponse.SERVER_ERROR);
}
return res.json({...ServerStdResponse.OK, data: resourceListRes});
return res.json({ ...ServerStdResponse.OK, data: resourceListRes });
}
}

View File

@@ -1,6 +1,5 @@
import { API } from "../Plugs/API/API";
import ServerStdResponse from "../ServerStdResponse";
import MySQLConnection from '../Plugs/MySQLConnection'
// 测试接口
class GetTest extends API {