import { sequelize } from '../../../modules/sequelize.ts'; import { DataTypes, Model } from 'sequelize'; type AppPermissionType = 'public' | 'private' | 'protected'; /** * 共享设置 * 1. 设置公共可以直接访问 * 2. 设置受保护需要登录后访问 * 3. 设置私有只有自己可以访问。\n * 受保护可以设置密码,设置访问的用户名。切换共享状态后,需要重新设置密码和用户名。 */ export interface AppData { files: { name: string; path: string }[]; permission?: { // 访问权限, 字段和minio的权限配置一致 share: AppPermissionType; // public, private(Only Self), protected(protected, 通过配置访问) usernames?: string; // 受保护的访问用户名,多个用逗号分隔 password?: string; // 受保护的访问密码 'expiration-time'?: string; // 受保护的访问过期时间 }; // 运行环境,browser, node, 或者其他,是数组 runtime?: string[]; } export enum AppStatus { running = 'running', stop = 'stop', } export type App = Partial>; /** * APP 管理 */ export class AppModel extends Model { declare id: string; declare data: AppData; declare title: string; declare description: string; declare version: string; declare key: string; declare uid: string; declare pid: string; // 是否是history路由代理模式。静态的直接转minio,而不需要缓存下来。 declare proxy: boolean; declare user: string; declare status: string; static async moveToNewUser(oldUserName: string, newUserName: string) { const appIds = await AppModel.findAll({ where: { user: oldUserName, }, attributes: ['id'], }); for (const app of appIds) { const appData = await AppModel.findByPk(app.id); appData.user = newUserName; const data = appData.data; data.files = await AppModel.getNewFiles(data.files, { oldUser: oldUserName, newUser: newUserName, }); appData.data = { ...data }; await appData.save({ fields: ['data', 'user'] }); } } static async getNewFiles(files: { name: string; path: string }[] = [], opts: { oldUser: string; newUser: string } = { oldUser: '', newUser: '' }) { const { oldUser, newUser } = opts; const _ = files.map((item) => { if (item.path.startsWith('http')) { return item; } if (oldUser && item.path.startsWith(oldUser)) { return item; } const paths = item.path.split('/'); return { ...item, path: newUser + '/' + paths.slice(1).join('/'), }; }); return _; } async getPublic() { const value = this.toJSON(); // 删除不需要的字段 const data = value.data; if (data && data.permission) { delete data.permission.usernames; delete data.permission.password; delete data.permission['expiration-time']; } value.data = data; return value; } } AppModel.init( { id: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4, comment: 'id', }, title: { type: DataTypes.STRING, defaultValue: '', }, description: { type: DataTypes.STRING, defaultValue: '', }, data: { type: DataTypes.JSONB, defaultValue: {}, }, version: { type: DataTypes.STRING, defaultValue: '', }, key: { type: DataTypes.STRING, // 和 uid 组合唯一 }, uid: { type: DataTypes.UUID, allowNull: true, }, pid: { type: DataTypes.UUID, allowNull: true, }, proxy: { type: DataTypes.BOOLEAN, defaultValue: false, }, user: { type: DataTypes.STRING, allowNull: true, }, status: { type: DataTypes.STRING, defaultValue: 'running', // stop, running }, }, { sequelize, tableName: 'kv_app', paranoid: true, indexes: [ { unique: true, fields: ['key', 'uid'], }, ], }, ); // AppModel.sync({ alter: true, logging: false }).catch((e) => { // console.error('AppModel sync', e); // });