Files
code-center/src/routes/app-manager/list.ts

376 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { App, CustomError } from '@kevisual/router';
import { AppModel, AppListModel } from './module/index.ts';
import { app, redis } from '@/app.ts';
import { uniqBy } from 'lodash-es';
import { getUidByUsername, prefixFix } from './util.ts';
import { deleteFiles, getMinioListAndSetToAppList } from '../file/index.ts';
import { setExpire } from './revoke.ts';
import { User } from '@/models/user.ts';
app
.route({
path: 'app',
key: 'list',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const data = ctx.query.data || {};
if (!data.key) {
throw new CustomError('key is required');
}
const list = await AppListModel.findAll({
order: [['updatedAt', 'DESC']],
where: {
uid: tokenUser.id,
key: data.key,
},
logging: false,
});
ctx.body = list.map((item) => prefixFix(item, tokenUser.username));
return ctx;
})
.addTo(app);
app
.route({
path: 'app',
key: 'get',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const id = ctx.query.id;
const { key, version } = ctx.query?.data || {};
if (!id && (!key || !version)) {
throw new CustomError('id is required');
}
let am: AppListModel;
if (id) {
am = await AppListModel.findByPk(id);
} else if (key && version) {
am = await AppListModel.findOne({
where: {
key,
version,
uid: tokenUser.id,
},
});
}
if (!am) {
throw new CustomError('app not found');
}
ctx.body = prefixFix(am, tokenUser.username);
})
.addTo(app);
app
.route({
path: 'app',
key: 'update',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { data, id, ...rest } = ctx.query.data;
if (id) {
const app = await AppListModel.findByPk(id);
if (app) {
const newData = { ...app.data, ...data };
const newApp = await app.update({ data: newData, ...rest });
ctx.body = newApp;
setExpire(newApp.id, 'test');
} else {
throw new CustomError('app not found');
}
return;
}
if (!rest.key) {
throw new CustomError('key is required');
}
const app = await AppListModel.create({ data, ...rest, uid: tokenUser.id });
ctx.body = app;
return ctx;
})
.addTo(app);
app
.route({
path: 'app',
key: 'delete',
middleware: ['auth'],
})
.define(async (ctx) => {
const id = ctx.query.id;
const deleteFile = !!ctx.query.deleteFile; // 是否删除文件, 默认不删除
if (!id) {
throw new CustomError('id is required');
}
const app = await AppListModel.findByPk(id);
if (!app) {
throw new CustomError('app not found');
}
const am = await AppModel.findOne({ where: { key: app.key, uid: app.uid } });
if (!am) {
throw new CustomError('app not found');
}
if (am.version === app.version) {
throw new CustomError('app is published');
}
const files = app.data.files || [];
if (deleteFile && files.length > 0) {
await deleteFiles(files.map((item) => item.path));
}
await app.destroy({
force: true,
});
ctx.body = 'success';
return ctx;
})
.addTo(app);
app
.route({
path: 'app',
key: 'canUploadFiles',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { appKey, version } = ctx.query.data;
if (!appKey) {
throw new CustomError('appKey is required');
}
const app = await AppListModel.findOne({ where: { version: version, key: appKey, uid: tokenUser.id } });
if (!app) {
throw new CustomError('app not found');
}
ctx.body = app;
})
.addTo(app);
app
.route({
path: 'app',
key: 'uploadFiles',
middleware: ['auth'],
isDebug: true,
})
.define(async (ctx) => {
try {
const tokenUser = ctx.state.tokenUser;
const { appKey, files, version, username, description } = ctx.query.data;
if (!appKey) {
throw new CustomError('appKey is required');
}
if (!files || !files.length) {
throw new CustomError('files is required');
}
let uid = tokenUser.id;
let userPrefix = tokenUser.username;
if (username) {
try {
const _user = await User.getUserByToken(ctx.query.token);
if (_user.hasUser(username)) {
const upUser = await User.findOne({ where: { username } });
uid = upUser.id;
userPrefix = username;
}
} catch (e) {
console.log('getUserByToken error', e);
throw new CustomError('user not found');
}
}
let am = await AppModel.findOne({ where: { key: appKey, uid } });
let appIsNew = false;
if (!am) {
appIsNew = true;
am = await AppModel.create({
user: userPrefix,
key: appKey,
uid,
version: version || '0.0.0',
title: appKey,
proxy: appKey.includes('center') ? false : true,
description: description || '',
data: {
files: files || [],
},
});
}
let app = await AppListModel.findOne({ where: { version: version, key: appKey, uid: uid } });
if (!app) {
app = await AppListModel.create({
key: appKey,
version,
uid: uid,
data: {
files: [],
},
});
}
const dataFiles = app.data.files || [];
const newFiles = uniqBy([...dataFiles, ...files], 'name');
const res = await app.update({ data: { ...app.data, files: newFiles } });
if (version === am.version && !appIsNew) {
await am.update({ data: { ...am.data, files: newFiles } });
}
setExpire(app.id, 'test');
ctx.body = prefixFix(res, userPrefix);
} catch (e) {
console.log('update error', e);
throw new CustomError(e.message);
}
})
.addTo(app);
app
.route({
path: 'app',
key: 'publish',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { id, username, appKey, version } = ctx.query.data;
if (!id && !appKey) {
throw new CustomError('id or appKey is required');
}
const uid = await getUidByUsername(app, ctx, username);
let appList: AppListModel | null = null;
if (id) {
appList = await AppListModel.findByPk(id);
if (appList?.uid !== uid) {
throw new CustomError('no permission');
}
}
if (!appList && appKey) {
if (!version) {
throw new CustomError('version is required');
}
appList = await AppListModel.findOne({ where: { key: appKey, version, uid } });
}
if (!appList) {
throw new CustomError('app not found');
}
const files = appList.data.files || [];
const am = await AppModel.findOne({ where: { key: appList.key, uid: uid } });
if (!am) {
throw new CustomError('app not found');
}
await am.update({ data: { ...am.data, files }, version: appList.version });
setExpire(appList.key, am.user);
ctx.body = {
key: appList.key,
version: appList.version,
appManager: am,
user: am.user,
};
})
.addTo(app);
app
.route({
path: 'app',
key: 'getApp',
})
.define(async (ctx) => {
const { user, key, id } = ctx.query.data;
let app;
if (id) {
app = await AppModel.findByPk(id);
} else if (user && key) {
app = await AppModel.findOne({ where: { user, key } });
} else {
throw new CustomError('user or key is required');
}
if (!app) {
throw new CustomError('app not found');
}
ctx.body = app;
})
.addTo(app);
app
.route({
path: 'app',
key: 'get-minio-list',
description: '获取minio列表',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { key, version } = ctx.query?.data || {};
if (!key || !version) {
throw new CustomError('key and version are required');
}
const files = await getMinioListAndSetToAppList({ username: tokenUser.username, appKey: key, version });
ctx.body = files;
})
.addTo(app);
app
.route({
path: 'app',
key: 'detectVersionList',
description: '检测版本列表minio中的数据自己上传后根据版本信息进行替换',
middleware: ['auth'],
})
.define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
let { appKey, version, username } = ctx.query?.data || {};
if (!appKey || !version) {
throw new CustomError('appKey and version are required');
}
const uid = await getUidByUsername(app, ctx, username);
let appList = await AppListModel.findOne({ where: { key: appKey, version, uid } });
if (!appList) {
appList = await AppListModel.create({
key: appKey,
version,
uid,
data: {
files: [],
},
});
}
const checkUsername = username || tokenUser.username;
const files = await getMinioListAndSetToAppList({ username: checkUsername, appKey, version });
const newFiles = files.map((item) => {
return {
name: item.name.replace(`${checkUsername}/${appKey}/${version}/`, ''),
path: item.name,
};
});
let appListFiles = appList.data?.files || [];
const needAddFiles = newFiles.map((item) => {
const findFile = appListFiles.find((appListFile) => appListFile.name === item.name);
if (findFile && findFile.name === item.name) {
return { ...findFile, ...item };
}
return item;
});
await appList.update({ data: { files: needAddFiles } });
setExpire(appList.id, 'test');
let am = await AppModel.findOne({ where: { key: appKey, uid } });
if (!am) {
am = await AppModel.create({
title: appKey,
key: appKey,
version: version || '0.0.0',
user: checkUsername,
uid,
data: { files: needAddFiles },
proxy: appKey.includes('center') ? false : true,
});
} else {
const appModel = await AppModel.findOne({ where: { key: appKey, version, uid } });
if (appModel) {
await appModel.update({ data: { files: needAddFiles } });
setExpire(appModel.key, appModel.user);
}
}
ctx.body = appList;
})
.addTo(app);