config
This commit is contained in:
parent
efef48a1b0
commit
d947043a16
@ -4,8 +4,11 @@ import * as redisLib from './modules/redis.ts';
|
|||||||
import * as minioLib from './modules/minio.ts';
|
import * as minioLib from './modules/minio.ts';
|
||||||
import * as sequelizeLib from './modules/sequelize.ts';
|
import * as sequelizeLib from './modules/sequelize.ts';
|
||||||
import { useContextKey, useContext } from '@kevisual/use-config/context';
|
import { useContextKey, useContext } from '@kevisual/use-config/context';
|
||||||
|
import { SimpleRouter } from '@kevisual/router/simple';
|
||||||
|
|
||||||
useConfig();
|
useConfig();
|
||||||
|
export const router = useContextKey('router', () => new SimpleRouter());
|
||||||
|
|
||||||
export const redis = useContextKey('redis', () => redisLib.redis);
|
export const redis = useContextKey('redis', () => redisLib.redis);
|
||||||
export const redisPublisher = useContextKey('redisPublisher', () => redisLib.redisPublisher);
|
export const redisPublisher = useContextKey('redisPublisher', () => redisLib.redisPublisher);
|
||||||
export const redisSubscriber = useContextKey('redisSubscriber', () => redisLib.redisSubscriber);
|
export const redisSubscriber = useContextKey('redisSubscriber', () => redisLib.redisSubscriber);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { IncomingForm } from 'formidable';
|
import { IncomingForm } from 'formidable';
|
||||||
import { checkAuth } from '../middleware/auth.ts';
|
import { checkAuth } from '../middleware/auth.ts';
|
||||||
import { router } from '../router.ts';
|
import { router, clients, writeEvents } from '../router.ts';
|
||||||
import { error } from '../middleware/auth.ts';
|
import { error } from '../middleware/auth.ts';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { clients } from '../upload.ts';
|
|
||||||
import { useFileStore } from '@kevisual/use-config/file-store';
|
import { useFileStore } from '@kevisual/use-config/file-store';
|
||||||
import { app, minioClient } from '@/app.ts';
|
import { app, minioClient } from '@/app.ts';
|
||||||
import { bucketName } from '@/modules/minio.ts';
|
import { bucketName } from '@/modules/minio.ts';
|
||||||
@ -29,7 +28,6 @@ router.post('/api/micro-app/upload', async (req, res) => {
|
|||||||
keepExtensions: true, // 保留文件
|
keepExtensions: true, // 保留文件
|
||||||
hashAlgorithm: 'md5', // 文件哈希算法
|
hashAlgorithm: 'md5', // 文件哈希算法
|
||||||
});
|
});
|
||||||
const taskId = req.headers['task-id'] as string;
|
|
||||||
form.on('progress', (bytesReceived, bytesExpected) => {
|
form.on('progress', (bytesReceived, bytesExpected) => {
|
||||||
const progress = (bytesReceived / bytesExpected) * 100;
|
const progress = (bytesReceived / bytesExpected) * 100;
|
||||||
console.log(`Upload progress: ${progress.toFixed(2)}%`);
|
console.log(`Upload progress: ${progress.toFixed(2)}%`);
|
||||||
@ -37,7 +35,7 @@ router.post('/api/micro-app/upload', async (req, res) => {
|
|||||||
progress: progress.toFixed(2),
|
progress: progress.toFixed(2),
|
||||||
message: `Upload progress: ${progress.toFixed(2)}%`,
|
message: `Upload progress: ${progress.toFixed(2)}%`,
|
||||||
};
|
};
|
||||||
clients.get(taskId)?.client?.write?.(`${JSON.stringify(data)}\n`);
|
writeEvents(req, data);
|
||||||
});
|
});
|
||||||
// 解析上传的文件
|
// 解析上传的文件
|
||||||
form.parse(req, async (err, fields, files) => {
|
form.parse(req, async (err, fields, files) => {
|
||||||
|
22
src/routes-simple/event.ts
Normal file
22
src/routes-simple/event.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { router, error, checkAuth, clients, getTaskId } from './router.ts';
|
||||||
|
|
||||||
|
router.get('/api/events', async (req, res) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
'Content-Type': 'text/event-stream',
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
Connection: 'keep-alive',
|
||||||
|
});
|
||||||
|
const tokenUser = await checkAuth(req, res);
|
||||||
|
if (!tokenUser) return;
|
||||||
|
const taskId = getTaskId(req);
|
||||||
|
if (!taskId) {
|
||||||
|
res.end(error('task-id is required'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 将客户端连接推送到 clients 数组
|
||||||
|
clients.set(taskId, { client: res, tokenUser });
|
||||||
|
// 移除客户端连接
|
||||||
|
req.on('close', () => {
|
||||||
|
clients.delete(taskId);
|
||||||
|
});
|
||||||
|
});
|
@ -1,24 +1,25 @@
|
|||||||
import { User } from '@/models/user.ts';
|
import { User } from '@/models/user.ts';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
|
import cookie from 'cookie';
|
||||||
export const error = (msg: string, code = 500) => {
|
export const error = (msg: string, code = 500) => {
|
||||||
return JSON.stringify({ code, message: msg });
|
return JSON.stringify({ code, message: msg });
|
||||||
};
|
};
|
||||||
export const checkAuth = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
export const checkAuth = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||||
let token = '';
|
let token = (req.headers?.['authorization'] as string) || '';
|
||||||
const authroization = req.headers?.['authorization'] as string;
|
|
||||||
const url = new URL(req.url || '', 'http://localhost');
|
const url = new URL(req.url || '', 'http://localhost');
|
||||||
const resNoPermission = () => {
|
const resNoPermission = () => {
|
||||||
res.statusCode = 401;
|
res.statusCode = 401;
|
||||||
res.end(error('Invalid authorization'));
|
res.end(error('Invalid authorization'));
|
||||||
return { tokenUser: null, token: null };
|
return { tokenUser: null, token: null };
|
||||||
};
|
};
|
||||||
if (authroization) {
|
if (!token) {
|
||||||
// return resNoPermission();
|
|
||||||
token = authroization.split(' ')[1];
|
|
||||||
} else if (url.searchParams.get('token')) {
|
|
||||||
token = url.searchParams.get('token') || '';
|
token = url.searchParams.get('token') || '';
|
||||||
} else {
|
}
|
||||||
|
if (!token) {
|
||||||
|
const parsedCookies = cookie.parse(req.headers.cookie || '');
|
||||||
|
token = parsedCookies.token || '';
|
||||||
|
}
|
||||||
|
if (!token) {
|
||||||
return resNoPermission();
|
return resNoPermission();
|
||||||
}
|
}
|
||||||
let tokenUser;
|
let tokenUser;
|
||||||
|
@ -1,3 +1,31 @@
|
|||||||
import { SimpleRouter } from '@kevisual/router/simple';
|
import { router } from '@/app.ts';
|
||||||
|
import http from 'http';
|
||||||
import { useContextKey } from '@kevisual/use-config/context';
|
import { useContextKey } from '@kevisual/use-config/context';
|
||||||
export const router = useContextKey('router', () => new SimpleRouter());
|
import { checkAuth, error } from './middleware/auth.ts';
|
||||||
|
export { router, checkAuth, error };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件客户端
|
||||||
|
*/
|
||||||
|
const eventClientsInit = () => {
|
||||||
|
const clients = new Map<string, { client?: http.ServerResponse; [key: string]: any }>();
|
||||||
|
return clients;
|
||||||
|
};
|
||||||
|
export const clients = useContextKey('event-clients', () => eventClientsInit());
|
||||||
|
/**
|
||||||
|
* 获取 task-id
|
||||||
|
* @param req
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getTaskId = (req: http.IncomingMessage) => {
|
||||||
|
return req.headers['task-id'] as string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 写入事件
|
||||||
|
* @param req
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export const writeEvents = (req: http.IncomingMessage, data: any) => {
|
||||||
|
const taskId = getTaskId(req);
|
||||||
|
taskId && clients.get(taskId)?.client?.write?.(`${JSON.stringify(data)}\n`);
|
||||||
|
};
|
||||||
|
@ -9,7 +9,7 @@ import { bucketName } from '@/modules/minio.ts';
|
|||||||
import { getContentType } from '@/utils/get-content-type.ts';
|
import { getContentType } from '@/utils/get-content-type.ts';
|
||||||
import { User } from '@/models/user.ts';
|
import { User } from '@/models/user.ts';
|
||||||
import { getContainerById } from '@/routes/container/module/get-container-file.ts';
|
import { getContainerById } from '@/routes/container/module/get-container-file.ts';
|
||||||
import { router } from './router.ts';
|
import { router, error, checkAuth, clients, writeEvents } from './router.ts';
|
||||||
import './index.ts';
|
import './index.ts';
|
||||||
|
|
||||||
const filePath = useFileStore('upload', { needExists: true });
|
const filePath = useFileStore('upload', { needExists: true });
|
||||||
@ -21,29 +21,6 @@ const cacheFilePath = useFileStore('cache-file', { needExists: true });
|
|||||||
// -F "description=This is a test upload" \
|
// -F "description=This is a test upload" \
|
||||||
// -F "username=testuser"
|
// -F "username=testuser"
|
||||||
|
|
||||||
export const clients = new Map<string, { client?: http.ServerResponse; [key: string]: any }>();
|
|
||||||
|
|
||||||
const error = (msg: string, code = 500) => {
|
|
||||||
return JSON.stringify({ code, message: msg });
|
|
||||||
};
|
|
||||||
const checkAuth = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
|
||||||
const authroization = req.headers?.['authorization'] as string;
|
|
||||||
if (!authroization) {
|
|
||||||
res.statusCode = 401;
|
|
||||||
res.end(error('Invalid authorization'));
|
|
||||||
return { tokenUser: null, token: null };
|
|
||||||
}
|
|
||||||
const token = authroization.split(' ')[1];
|
|
||||||
let tokenUser;
|
|
||||||
try {
|
|
||||||
tokenUser = await User.verifyToken(token);
|
|
||||||
} catch (e) {
|
|
||||||
res.statusCode = 401;
|
|
||||||
res.end(error('Invalid token'));
|
|
||||||
return { tokenUser: null, token: null };
|
|
||||||
}
|
|
||||||
return { tokenUser, token };
|
|
||||||
};
|
|
||||||
router.get('/api/app/upload', async (req, res) => {
|
router.get('/api/app/upload', async (req, res) => {
|
||||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
res.end('Upload API is ready');
|
res.end('Upload API is ready');
|
||||||
@ -59,6 +36,16 @@ router.post('/api/upload', async (req, res) => {
|
|||||||
uploadDir: filePath, // 上传文件存储目录
|
uploadDir: filePath, // 上传文件存储目录
|
||||||
allowEmptyFiles: true, // 允许空文件
|
allowEmptyFiles: true, // 允许空文件
|
||||||
});
|
});
|
||||||
|
form.on('progress', (bytesReceived, bytesExpected) => {
|
||||||
|
const progress = (bytesReceived / bytesExpected) * 100;
|
||||||
|
console.log(`Upload progress: ${progress.toFixed(2)}%`);
|
||||||
|
const data = {
|
||||||
|
progress: progress.toFixed(2),
|
||||||
|
message: `Upload progress: ${progress.toFixed(2)}%`,
|
||||||
|
};
|
||||||
|
writeEvents(req, data);
|
||||||
|
});
|
||||||
|
|
||||||
// 解析上传的文件
|
// 解析上传的文件
|
||||||
form.parse(req, async (err, fields, files) => {
|
form.parse(req, async (err, fields, files) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -101,7 +88,6 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
const { tokenUser, token } = await checkAuth(req, res);
|
const { tokenUser, token } = await checkAuth(req, res);
|
||||||
if (!tokenUser) return;
|
if (!tokenUser) return;
|
||||||
//
|
|
||||||
// 使用 formidable 解析 multipart/form-data
|
// 使用 formidable 解析 multipart/form-data
|
||||||
const form = new IncomingForm({
|
const form = new IncomingForm({
|
||||||
multiples: true, // 支持多文件上传
|
multiples: true, // 支持多文件上传
|
||||||
@ -119,8 +105,7 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
progress: progress.toFixed(2),
|
progress: progress.toFixed(2),
|
||||||
message: `Upload progress: ${progress.toFixed(2)}%`,
|
message: `Upload progress: ${progress.toFixed(2)}%`,
|
||||||
};
|
};
|
||||||
// 向所有连接的客户端推送进度信息
|
writeEvents(req, data);
|
||||||
clients.forEach((client) => client.write(`${JSON.stringify(data)}\n`));
|
|
||||||
});
|
});
|
||||||
// 解析上传的文件
|
// 解析上传的文件
|
||||||
form.parse(req, async (err, fields, files) => {
|
form.parse(req, async (err, fields, files) => {
|
||||||
@ -225,24 +210,7 @@ router.post('/api/app/upload', async (req, res) => {
|
|||||||
res.end(JSON.stringify(data));
|
res.end(JSON.stringify(data));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
router.get('/api/events', async (req, res) => {
|
|
||||||
if (req.url === '/api/events') {
|
|
||||||
res.writeHead(200, {
|
|
||||||
'Content-Type': 'text/event-stream',
|
|
||||||
'Cache-Control': 'no-cache',
|
|
||||||
Connection: 'keep-alive',
|
|
||||||
});
|
|
||||||
const tokenUser = await checkAuth(req, res);
|
|
||||||
if (!tokenUser) return;
|
|
||||||
const taskId = req.headers['task-id'] as string;
|
|
||||||
// 将客户端连接推送到 clients 数组
|
|
||||||
clients.set(taskId, { client: res, tokenUser });
|
|
||||||
// 移除客户端连接
|
|
||||||
req.on('close', () => {
|
|
||||||
clients.delete(taskId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
router.get('/api/container/file/:id', async (req, res) => {
|
router.get('/api/container/file/:id', async (req, res) => {
|
||||||
const id = req.params.id;
|
const id = req.params.id;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
2
src/routes/config/index.ts
Normal file
2
src/routes/config/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import './list.ts';
|
||||||
|
import './upload-config.ts';
|
21
src/routes/config/list.ts
Normal file
21
src/routes/config/list.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { app } from '@/app.ts';
|
||||||
|
import { ConfigModel } from './models/model.ts';
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'config',
|
||||||
|
key: 'list',
|
||||||
|
middleware: ['auth'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { id } = ctx.state.tokenUser;
|
||||||
|
const config = await ConfigModel.findAll({
|
||||||
|
where: {
|
||||||
|
uid: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
ctx.body = {
|
||||||
|
list: config,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
140
src/routes/config/models/model.ts
Normal file
140
src/routes/config/models/model.ts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { useContextKey } from '@kevisual/use-config/context';
|
||||||
|
import { sequelize } from '../../../modules/sequelize.ts';
|
||||||
|
import { DataTypes, Model } from 'sequelize';
|
||||||
|
|
||||||
|
export interface ConfigData {
|
||||||
|
key?: string;
|
||||||
|
version?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Config = Partial<InstanceType<typeof ConfigModel>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户配置
|
||||||
|
*/
|
||||||
|
export class ConfigModel extends Model {
|
||||||
|
declare id: string;
|
||||||
|
declare title: string;
|
||||||
|
declare description: string;
|
||||||
|
declare tags: string[];
|
||||||
|
declare key: string;
|
||||||
|
declare data: ConfigData; // files
|
||||||
|
declare uid: string;
|
||||||
|
/**
|
||||||
|
* 获取用户配置
|
||||||
|
* @param key 配置key
|
||||||
|
* @param opts 配置选项
|
||||||
|
* @param opts.uid 用户id
|
||||||
|
* @param opts.defaultData 默认数据
|
||||||
|
* @returns 配置
|
||||||
|
*/
|
||||||
|
static async getConfig(key: string, opts: { uid: string; defaultData?: any }) {
|
||||||
|
const [config, isNew] = await ConfigModel.findOrCreate({
|
||||||
|
where: { key, uid: opts.uid },
|
||||||
|
defaults: {
|
||||||
|
key,
|
||||||
|
title: key,
|
||||||
|
uid: opts.uid,
|
||||||
|
data: opts?.defaultData || {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
config: config,
|
||||||
|
isNew,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async setConfig(key: string, opts: { uid: string; data: any }) {
|
||||||
|
let config = await ConfigModel.findOne({
|
||||||
|
where: { key, uid: opts.uid },
|
||||||
|
});
|
||||||
|
if (config) {
|
||||||
|
config.data = { ...config.data, ...opts.data };
|
||||||
|
await config.save();
|
||||||
|
} else {
|
||||||
|
config = await ConfigModel.create({
|
||||||
|
title: key,
|
||||||
|
key,
|
||||||
|
uid: opts.uid,
|
||||||
|
data: opts.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取上传配置
|
||||||
|
* @param key 配置key
|
||||||
|
* @param opts 配置选项
|
||||||
|
* @param opts.uid 用户id
|
||||||
|
* @returns 配置
|
||||||
|
*/
|
||||||
|
static async getUploadConfig(opts: { uid: string }) {
|
||||||
|
const defaultConfig = {
|
||||||
|
key: 'upload',
|
||||||
|
type: 'upload',
|
||||||
|
version: '1.0.0',
|
||||||
|
};
|
||||||
|
const config = await ConfigModel.getConfig('upload', {
|
||||||
|
uid: opts.uid,
|
||||||
|
defaultData: defaultConfig,
|
||||||
|
});
|
||||||
|
const data = config.config.data;
|
||||||
|
const prefix = `/${data.key}/${data.version}`;
|
||||||
|
return {
|
||||||
|
config: config.config,
|
||||||
|
isNew: config.isNew,
|
||||||
|
prefix,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async setUploadConfig(opts: { uid: string; data: any }) {
|
||||||
|
const config = await ConfigModel.setConfig('upload', {
|
||||||
|
uid: opts.uid,
|
||||||
|
data: opts.data,
|
||||||
|
});
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigModel.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
primaryKey: true,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
comment: 'id',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
key: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
type: DataTypes.JSONB,
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: DataTypes.JSONB,
|
||||||
|
defaultValue: {},
|
||||||
|
},
|
||||||
|
uid: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
tableName: 'kv_config',
|
||||||
|
paranoid: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ConfigModel.sync({ alter: true, logging: false }).catch((e) => {
|
||||||
|
console.error('ConfigModel sync', e);
|
||||||
|
});
|
||||||
|
|
||||||
|
useContextKey('ConfigModel', () => ConfigModel);
|
34
src/routes/config/upload-config.ts
Normal file
34
src/routes/config/upload-config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { app } from '../../app.ts';
|
||||||
|
import { ConfigModel } from './models/model.ts';
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'config',
|
||||||
|
key: 'getUploadConfig',
|
||||||
|
middleware: ['auth'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { id } = ctx.state.tokenUser;
|
||||||
|
const config = await ConfigModel.getUploadConfig({
|
||||||
|
uid: id,
|
||||||
|
});
|
||||||
|
ctx.body = config;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'config',
|
||||||
|
key: 'setUploadConfig',
|
||||||
|
middleware: ['auth'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { id } = ctx.state.tokenUser;
|
||||||
|
const data = ctx.query.data || {};
|
||||||
|
const config = await ConfigModel.setUploadConfig({
|
||||||
|
uid: id,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
ctx.body = config;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
@ -15,3 +15,5 @@ import './file/index.ts';
|
|||||||
// import './packages/index.ts';
|
// import './packages/index.ts';
|
||||||
|
|
||||||
import './micro-app/index.ts';
|
import './micro-app/index.ts';
|
||||||
|
|
||||||
|
import './config/index.ts';
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ResourceData, ResourceModel } from './models/index.ts';
|
import { ResourceModel } from './models/index.ts';
|
||||||
import { app } from '../../app.ts';
|
import { app } from '../../app.ts';
|
||||||
import { CustomError } from '@kevisual/router';
|
|
||||||
|
|
||||||
app
|
app
|
||||||
.route({
|
.route({
|
||||||
@ -29,11 +28,11 @@ app
|
|||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const id = ctx.query.id;
|
const id = ctx.query.id;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new CustomError('id is required');
|
ctx.throw('id is required');
|
||||||
}
|
}
|
||||||
const rm = await ResourceModel.findByPk(id);
|
const rm = await ResourceModel.findByPk(id);
|
||||||
if (!rm) {
|
if (!rm) {
|
||||||
throw new CustomError('resource not found');
|
ctx.throw('resource not found');
|
||||||
}
|
}
|
||||||
ctx.body = rm;
|
ctx.body = rm;
|
||||||
return ctx;
|
return ctx;
|
||||||
@ -61,15 +60,16 @@ app
|
|||||||
.route({
|
.route({
|
||||||
path: 'resource',
|
path: 'resource',
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
|
middleware: ['auth'],
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const id = ctx.query.id;
|
const id = ctx.query.id;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new CustomError('id is required');
|
ctx.throw('id is required');
|
||||||
}
|
}
|
||||||
const resource = await ResourceModel.findByPk(id);
|
const resource = await ResourceModel.findByPk(id);
|
||||||
if (!resource) {
|
if (!resource) {
|
||||||
throw new CustomError('resource not found');
|
ctx.throw('resource not found');
|
||||||
}
|
}
|
||||||
await resource.destroy();
|
await resource.destroy();
|
||||||
ctx.body = 'success';
|
ctx.body = 'success';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user