161 lines
4.1 KiB
TypeScript
161 lines
4.1 KiB
TypeScript
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<InstanceType<typeof AppModel>>;
|
||
|
||
/**
|
||
* 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);
|
||
// });
|