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);