feat: 添加发布应用目录功能,增强应用版本管理和权限校验
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { App as AppType, AppList, AppData } from './module/app-drizzle.ts';
|
||||
import { app, db, schema } from '@/app.ts';
|
||||
import { app, db, oss, schema } from '@/app.ts';
|
||||
import { uniqBy } from 'es-toolkit';
|
||||
import { getUidByUsername, prefixFix } from './util.ts';
|
||||
import { deleteFiles, getMinioListAndSetToAppList } from '../file/index.ts';
|
||||
import { deleteFiles, getMinioList, getMinioListAndSetToAppList } from '../file/index.ts';
|
||||
import { setExpire } from './revoke.ts';
|
||||
import { User } from '@/models/user.ts';
|
||||
import { callDetectAppVersion } from './export.ts';
|
||||
@@ -47,6 +47,16 @@ app
|
||||
key: 'get',
|
||||
middleware: ['auth'],
|
||||
description: '获取应用详情,可以通过id,或者key+version来获取',
|
||||
metadata: {
|
||||
args: {
|
||||
data: z.object({
|
||||
id: z.string().optional(),
|
||||
version: z.string().optional(),
|
||||
key: z.string().optional(),
|
||||
create: z.boolean().optional().describe('如果应用版本不存在,是否创建应用版本记录,默认false'),
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
console.log('get app manager called');
|
||||
@@ -376,11 +386,88 @@ app
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app.route({
|
||||
path: 'app',
|
||||
key: 'publishDirectory',
|
||||
middleware: ['auth'],
|
||||
description: '发布应用目录,将某个版本的应用目录设置为当前应用的版本',
|
||||
metadata: {
|
||||
args: {
|
||||
data: z.object({
|
||||
key: z.string().describe('应用的唯一标识'),
|
||||
version: z.string().describe('应用版本'),
|
||||
directory: z.string().describe('应用目录'),
|
||||
})
|
||||
}
|
||||
}
|
||||
}).define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const { key, version, directory } = ctx.query.data;
|
||||
if (!key || !version || !directory) {
|
||||
ctx.throw('key, version and directory are required');
|
||||
}
|
||||
const username = tokenUser.username;
|
||||
const chunks = directory.split('/').filter((item) => item);
|
||||
const [_username, appWay, ...rest] = chunks;
|
||||
if (username !== _username) {
|
||||
ctx.throw('没有权限');
|
||||
}
|
||||
let newChunks = [];
|
||||
if (appWay === 'resources') {
|
||||
newChunks = [username, ...rest];
|
||||
} else if (appWay === 'ai') {
|
||||
newChunks = [username, 'ai', '1.0.0', ...rest];
|
||||
}
|
||||
const [_, originAppKey, originVersion] = newChunks.filter((item) => item);
|
||||
if (!originAppKey || !originVersion) {
|
||||
ctx.throw('目录不合法');
|
||||
}
|
||||
const pub = async () => {
|
||||
return await app.run({
|
||||
path: 'app',
|
||||
key: 'publish',
|
||||
payload: {
|
||||
data: {
|
||||
appKey: key,
|
||||
version,
|
||||
detect: true,
|
||||
},
|
||||
token: ctx.query.token,
|
||||
},
|
||||
})
|
||||
}
|
||||
// 如果发布的版本和当前版本不一致,则将目录下的文件复制到新的目录下
|
||||
if (originAppKey !== key || originVersion !== version) {
|
||||
const oldPrefix = newChunks.join('/') + '/';
|
||||
const newPrefix = `${username}/${key}/${version}/`;
|
||||
const listSource = await getMinioList<true>({ prefix: oldPrefix, recursive: true });
|
||||
for (const item of listSource) {
|
||||
const newName = item.name.slice(oldPrefix.length);
|
||||
await oss.copyObject(item.name, `${newPrefix}${newName}`);
|
||||
}
|
||||
}
|
||||
const appRes = await app.run({ path: 'app', key: 'get', payload: { data: { key, version, create: true }, token: ctx.query.token } });
|
||||
if (appRes.code !== 200) {
|
||||
ctx.throw(appRes.message || '获取应用信息失败');
|
||||
}
|
||||
const res = await pub();
|
||||
ctx.forward(res);
|
||||
|
||||
}).addTo(app);
|
||||
app
|
||||
.route({
|
||||
path: 'app',
|
||||
key: 'getApp',
|
||||
description: '获取应用信息,可以通过id,或者key+version来获取, 参数在data中传入',
|
||||
metadata: {
|
||||
args: {
|
||||
data: z.object({
|
||||
id: z.string().optional(),
|
||||
key: z.string().optional(),
|
||||
version: z.string().optional(),
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const { user, key, id } = ctx.query.data;
|
||||
|
||||
Reference in New Issue
Block a user