feat: update org operate
This commit is contained in:
parent
409067f13f
commit
d2280f6b89
@ -16,7 +16,8 @@
|
|||||||
"reload": "ssh light pm2 restart codecenter",
|
"reload": "ssh light pm2 restart codecenter",
|
||||||
"pub": "npm run build && npm run deploy && npm run reload",
|
"pub": "npm run build && npm run deploy && npm run reload",
|
||||||
"start": "pm2 start dist/app.mjs --name codecenter",
|
"start": "pm2 start dist/app.mjs --name codecenter",
|
||||||
"release": "node ./config/release/index.mjs"
|
"release": "node ./config/release/index.mjs",
|
||||||
|
"ssl": "ssl -L 6379:localhost:6379 light "
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"types": "types/index.d.ts",
|
"types": "types/index.d.ts",
|
||||||
@ -45,6 +46,7 @@
|
|||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"p-queue": "^8.1.0",
|
"p-queue": "^8.1.0",
|
||||||
"pg": "^8.13.3",
|
"pg": "^8.13.3",
|
||||||
|
"pm2": "^5.4.3",
|
||||||
"rollup-plugin-esbuild": "^6.2.1",
|
"rollup-plugin-esbuild": "^6.2.1",
|
||||||
"semver": "^7.7.1",
|
"semver": "^7.7.1",
|
||||||
"sequelize": "^6.37.5",
|
"sequelize": "^6.37.5",
|
||||||
@ -52,10 +54,10 @@
|
|||||||
"strip-ansi": "^7.1.0",
|
"strip-ansi": "^7.1.0",
|
||||||
"tar": "^7.4.3",
|
"tar": "^7.4.3",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"pm2": "^5.4.3",
|
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@kevisual/code-center-module": "^0.0.9",
|
||||||
"@kevisual/types": "^0.0.6",
|
"@kevisual/types": "^0.0.6",
|
||||||
"@rollup/plugin-alias": "^5.1.1",
|
"@rollup/plugin-alias": "^5.1.1",
|
||||||
"@rollup/plugin-commonjs": "^28.0.2",
|
"@rollup/plugin-commonjs": "^28.0.2",
|
||||||
|
29
pnpm-lock.yaml
generated
29
pnpm-lock.yaml
generated
@ -95,6 +95,9 @@ importers:
|
|||||||
specifier: ^3.24.2
|
specifier: ^3.24.2
|
||||||
version: 3.24.2
|
version: 3.24.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@kevisual/code-center-module':
|
||||||
|
specifier: ^0.0.9
|
||||||
|
version: 0.0.9(@kevisual/auth@1.0.5)(@kevisual/router@0.0.7)(@kevisual/use-config@1.0.8)(ioredis@5.5.0)(pg@8.13.3)(sequelize@6.37.5(pg@8.13.3))
|
||||||
'@kevisual/types':
|
'@kevisual/types':
|
||||||
specifier: ^0.0.6
|
specifier: ^0.0.6
|
||||||
version: 0.0.6
|
version: 0.0.6
|
||||||
@ -348,6 +351,16 @@ packages:
|
|||||||
'@kevisual/auth@1.0.5':
|
'@kevisual/auth@1.0.5':
|
||||||
resolution: {integrity: sha512-GwsLj7unKXi7lmMiIIgdig4LwwLiDJnOy15HHZR5gMbyK6s5/uJiMY5RXPB2+onGzTNDqFo/hXjsD2wkerHPVg==}
|
resolution: {integrity: sha512-GwsLj7unKXi7lmMiIIgdig4LwwLiDJnOy15HHZR5gMbyK6s5/uJiMY5RXPB2+onGzTNDqFo/hXjsD2wkerHPVg==}
|
||||||
|
|
||||||
|
'@kevisual/code-center-module@0.0.9':
|
||||||
|
resolution: {integrity: sha512-ErHTYUlJGXmeBV5RJezKbBRmTYVBABV0SVvcMvbWVWPNc13Zo5RvM29vnzY6w3b6/cpnpWBi7Vx8WGFrcsMOkw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@kevisual/auth': ^1.0.5
|
||||||
|
'@kevisual/router': ^0.0.7
|
||||||
|
'@kevisual/use-config': ^1.0.8
|
||||||
|
ioredis: ^5.5.0
|
||||||
|
pg: ^8.13.3
|
||||||
|
sequelize: ^6.37.5
|
||||||
|
|
||||||
'@kevisual/local-app-manager@0.1.9':
|
'@kevisual/local-app-manager@0.1.9':
|
||||||
resolution: {integrity: sha512-oppYUjvpPg/7gBw1h3dX63fhxB8MvGc74yGgIM4JifvSuOYLcZ9oZyauYV+5lQVh2tjJImOuUmRHnVXu1FWKDQ==}
|
resolution: {integrity: sha512-oppYUjvpPg/7gBw1h3dX63fhxB8MvGc74yGgIM4JifvSuOYLcZ9oZyauYV+5lQVh2tjJImOuUmRHnVXu1FWKDQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2562,6 +2575,22 @@ snapshots:
|
|||||||
|
|
||||||
'@kevisual/auth@1.0.5': {}
|
'@kevisual/auth@1.0.5': {}
|
||||||
|
|
||||||
|
'@kevisual/code-center-module@0.0.9(@kevisual/auth@1.0.5)(@kevisual/router@0.0.7)(@kevisual/use-config@1.0.8)(ioredis@5.5.0)(pg@8.13.3)(sequelize@6.37.5(pg@8.13.3))':
|
||||||
|
dependencies:
|
||||||
|
'@kevisual/auth': 1.0.5
|
||||||
|
'@kevisual/router': 0.0.7
|
||||||
|
'@kevisual/use-config': 1.0.8
|
||||||
|
ioredis: 5.5.0
|
||||||
|
nanoid: 5.1.2
|
||||||
|
pg: 8.13.3
|
||||||
|
sequelize: 6.37.5(pg@8.13.3)
|
||||||
|
socket.io: 4.8.1
|
||||||
|
zod: 3.24.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bufferutil
|
||||||
|
- supports-color
|
||||||
|
- utf-8-validate
|
||||||
|
|
||||||
'@kevisual/local-app-manager@0.1.9(@kevisual/router@0.0.7)(@kevisual/types@0.0.6)(@kevisual/use-config@1.0.8)(pm2@5.4.3)':
|
'@kevisual/local-app-manager@0.1.9(@kevisual/router@0.0.7)(@kevisual/types@0.0.6)(@kevisual/use-config@1.0.8)(pm2@5.4.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/router': 0.0.7
|
'@kevisual/router': 0.0.7
|
||||||
|
@ -1,44 +1,48 @@
|
|||||||
import { DataTypes, Model, Sequelize } from 'sequelize';
|
// import { DataTypes, Model, Sequelize } from 'sequelize';
|
||||||
import { useContextKey } from '@kevisual/use-config/context';
|
// import { useContextKey } from '@kevisual/use-config/context';
|
||||||
const sequelize = useContextKey<Sequelize>('sequelize');
|
// const sequelize = useContextKey<Sequelize>('sequelize');
|
||||||
export class Org extends Model {
|
// export class Org extends Model {
|
||||||
declare id: string;
|
// declare id: string;
|
||||||
declare username: string;
|
// declare username: string;
|
||||||
declare description: string;
|
// declare description: string;
|
||||||
declare users: { role: string; uid: string }[];
|
// declare users: { role: string; uid: string }[];
|
||||||
}
|
// }
|
||||||
|
|
||||||
Org.init(
|
// Org.init(
|
||||||
{
|
// {
|
||||||
id: {
|
// id: {
|
||||||
type: DataTypes.UUID,
|
// type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
// primaryKey: true,
|
||||||
defaultValue: DataTypes.UUIDV4,
|
// defaultValue: DataTypes.UUIDV4,
|
||||||
},
|
// },
|
||||||
username: {
|
// username: {
|
||||||
type: DataTypes.STRING,
|
// type: DataTypes.STRING,
|
||||||
allowNull: false,
|
// allowNull: false,
|
||||||
unique: true,
|
// unique: true,
|
||||||
},
|
// },
|
||||||
description: {
|
// description: {
|
||||||
type: DataTypes.STRING,
|
// type: DataTypes.STRING,
|
||||||
allowNull: true,
|
// allowNull: true,
|
||||||
},
|
// },
|
||||||
users: {
|
// users: {
|
||||||
type: DataTypes.JSONB,
|
// type: DataTypes.JSONB,
|
||||||
allowNull: true,
|
// allowNull: true,
|
||||||
defaultValue: [],
|
// defaultValue: [],
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
sequelize,
|
// sequelize,
|
||||||
modelName: 'cf_org',
|
// modelName: 'cf_org',
|
||||||
paranoid: true,
|
// paranoid: true,
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
Org.sync({ alter: true, logging: false }).catch((e) => {
|
// Org.sync({ alter: true, logging: false }).catch((e) => {
|
||||||
console.error('Org sync', e);
|
// console.error('Org sync', e);
|
||||||
});
|
// });
|
||||||
|
|
||||||
useContextKey('OrgModel', () => Org);
|
// useContextKey('OrgModel', () => Org);
|
||||||
|
import { Org, OrgInit } from '@kevisual/code-center-module/models';
|
||||||
|
export { Org };
|
||||||
|
|
||||||
|
OrgInit();
|
||||||
|
@ -1,287 +1,293 @@
|
|||||||
import { useConfig } from '@kevisual/use-config';
|
// import { useConfig } from '@kevisual/use-config';
|
||||||
import { DataTypes, Model, Op, Sequelize } from 'sequelize';
|
// import { DataTypes, Model, Op, Sequelize } from 'sequelize';
|
||||||
import { createToken, checkToken } from '@kevisual/auth';
|
// import { createToken, checkToken } from '@kevisual/auth';
|
||||||
import { cryptPwd } from '@kevisual/auth';
|
// import { cryptPwd } from '@kevisual/auth';
|
||||||
import { customRandom, nanoid, customAlphabet } from 'nanoid';
|
// import { customRandom, nanoid, customAlphabet } from 'nanoid';
|
||||||
import { CustomError } from '@kevisual/router';
|
// import { CustomError } from '@kevisual/router';
|
||||||
import { Org } from './org.ts';
|
// import { Org } from './org.ts';
|
||||||
|
|
||||||
import { useContextKey } from '@kevisual/use-config/context';
|
// import { useContextKey } from '@kevisual/use-config/context';
|
||||||
import { Redis } from 'ioredis';
|
// import { Redis } from 'ioredis';
|
||||||
export const redis = useContextKey<Redis>('redis');
|
// export const redis = useContextKey<Redis>('redis');
|
||||||
const sequelize = useContextKey<Sequelize>('sequelize');
|
// const sequelize = useContextKey<Sequelize>('sequelize');
|
||||||
const config = useConfig<{ tokenSecret: string }>();
|
// const config = useConfig<{ tokenSecret: string }>();
|
||||||
|
|
||||||
type UserData = {
|
// type UserData = {
|
||||||
orgs?: string[];
|
// orgs?: string[];
|
||||||
};
|
// };
|
||||||
export class User extends Model {
|
// export class User extends Model {
|
||||||
declare id: string;
|
// declare id: string;
|
||||||
declare username: string;
|
// declare username: string;
|
||||||
declare nickname: string; // 昵称
|
// declare nickname: string; // 昵称
|
||||||
declare alias: string; // 别名
|
// declare alias: string; // 别名
|
||||||
declare password: string;
|
// declare password: string;
|
||||||
declare salt: string;
|
// declare salt: string;
|
||||||
declare needChangePassword: boolean;
|
// declare needChangePassword: boolean;
|
||||||
declare description: string;
|
// declare description: string;
|
||||||
declare data: UserData;
|
// declare data: UserData;
|
||||||
declare type: string; // user | org | visitor
|
// declare type: string; // user | org | visitor
|
||||||
declare owner: string;
|
// declare owner: string;
|
||||||
declare orgId: string;
|
// declare orgId: string;
|
||||||
declare email: string;
|
// declare email: string;
|
||||||
declare avatar: string;
|
// declare avatar: string;
|
||||||
tokenUser: any;
|
// tokenUser: any;
|
||||||
setTokenUser(tokenUser: any) {
|
// setTokenUser(tokenUser: any) {
|
||||||
this.tokenUser = tokenUser;
|
// this.tokenUser = tokenUser;
|
||||||
}
|
// }
|
||||||
/**
|
// /**
|
||||||
* uid 是用于 orgId 的用户id 真实用户的id
|
// * uid 是用于 orgId 的用户id 真实用户的id
|
||||||
* @param uid
|
// * @param uid
|
||||||
* @returns
|
// * @returns
|
||||||
*/
|
// */
|
||||||
async createToken(uid?: string, loginType?: 'default' | 'plugin' | 'month' | 'season' | 'year') {
|
// async createToken(uid?: string, loginType?: 'default' | 'plugin' | 'month' | 'season' | 'year') {
|
||||||
const { id, username, type } = this;
|
// const { id, username, type } = this;
|
||||||
let expireTime = 60 * 60 * 24 * 7; // 7 days
|
// let expireTime = 60 * 60 * 24 * 7; // 7 days
|
||||||
switch (loginType) {
|
// switch (loginType) {
|
||||||
case 'plugin':
|
// case 'plugin':
|
||||||
expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
// expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
||||||
break;
|
// break;
|
||||||
case 'month':
|
// case 'month':
|
||||||
expireTime = 60 * 60 * 24 * 30; // 30 days
|
// expireTime = 60 * 60 * 24 * 30; // 30 days
|
||||||
break;
|
// break;
|
||||||
case 'season':
|
// case 'season':
|
||||||
expireTime = 60 * 60 * 24 * 30 * 3; // 90 days
|
// expireTime = 60 * 60 * 24 * 30 * 3; // 90 days
|
||||||
break;
|
// break;
|
||||||
case 'year':
|
// case 'year':
|
||||||
expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
// expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
const now = new Date().getTime();
|
// const now = new Date().getTime();
|
||||||
const token = await createToken({ id, username, uid, type }, config.tokenSecret);
|
// const token = await createToken({ id, username, uid, type }, config.tokenSecret);
|
||||||
return { token, expireTime: now + expireTime };
|
// return { token, expireTime: now + expireTime };
|
||||||
}
|
// }
|
||||||
static async verifyToken(token: string) {
|
// static async verifyToken(token: string) {
|
||||||
const ct = await checkToken(token, config.tokenSecret);
|
// const ct = await checkToken(token, config.tokenSecret);
|
||||||
const tokenUser = ct.payload;
|
// const tokenUser = ct.payload;
|
||||||
return tokenUser;
|
// return tokenUser;
|
||||||
}
|
// }
|
||||||
static async createUser(username: string, password?: string, description?: string) {
|
// static async createUser(username: string, password?: string, description?: string) {
|
||||||
const user = await User.findOne({ where: { username } });
|
// const user = await User.findOne({ where: { username } });
|
||||||
if (user) {
|
// if (user) {
|
||||||
throw new CustomError('User already exists');
|
// throw new CustomError('User already exists');
|
||||||
}
|
// }
|
||||||
const salt = nanoid(6);
|
// const salt = nanoid(6);
|
||||||
let needChangePassword = !password;
|
// let needChangePassword = !password;
|
||||||
password = password || '123456';
|
// password = password || '123456';
|
||||||
const cPassword = cryptPwd(password, salt);
|
// const cPassword = cryptPwd(password, salt);
|
||||||
return await User.create({ username, password: cPassword, description, salt, needChangePassword });
|
// return await User.create({ username, password: cPassword, description, salt, needChangePassword });
|
||||||
}
|
// }
|
||||||
static async createOrg(username: string, owner: string, description?: string) {
|
// static async createOrg(username: string, owner: string, description?: string) {
|
||||||
const user = await User.findOne({ where: { username } });
|
// const user = await User.findOne({ where: { username } });
|
||||||
if (user) {
|
// if (user) {
|
||||||
throw new CustomError('User already exists');
|
// throw new CustomError('User already exists');
|
||||||
}
|
// }
|
||||||
const me = await User.findByPk(owner);
|
// const me = await User.findByPk(owner);
|
||||||
if (!me) {
|
// if (!me) {
|
||||||
throw new CustomError('Owner not found');
|
// throw new CustomError('Owner not found');
|
||||||
}
|
// }
|
||||||
if (me.type !== 'user') {
|
// if (me.type !== 'user') {
|
||||||
throw new CustomError('Owner type is not user');
|
// throw new CustomError('Owner type is not user');
|
||||||
}
|
// }
|
||||||
const org = await Org.create({ username, description, users: [{ uid: owner, role: 'owner' }] });
|
// const org = await Org.create({ username, description, users: [{ uid: owner, role: 'owner' }] });
|
||||||
const newUser = await User.create({ username, password: '', description, type: 'org', owner, orgId: org.id });
|
// const newUser = await User.create({ username, password: '', description, type: 'org', owner, orgId: org.id });
|
||||||
// owner add
|
// // owner add
|
||||||
await redis.del(`user:${me.id}:orgs`);
|
// await redis.del(`user:${me.id}:orgs`);
|
||||||
return newUser;
|
// return newUser;
|
||||||
}
|
// }
|
||||||
createPassword(password: string) {
|
// createPassword(password: string) {
|
||||||
const salt = this.salt;
|
// const salt = this.salt;
|
||||||
const cPassword = cryptPwd(password, salt);
|
// const cPassword = cryptPwd(password, salt);
|
||||||
this.password = cPassword;
|
// this.password = cPassword;
|
||||||
return cPassword;
|
// return cPassword;
|
||||||
}
|
// }
|
||||||
checkPassword(password: string) {
|
// checkPassword(password: string) {
|
||||||
const salt = this.salt;
|
// const salt = this.salt;
|
||||||
const cPassword = cryptPwd(password, salt);
|
// const cPassword = cryptPwd(password, salt);
|
||||||
return this.password === cPassword;
|
// return this.password === cPassword;
|
||||||
}
|
// }
|
||||||
async getInfo() {
|
// async getInfo() {
|
||||||
const orgs = await this.getOrgs();
|
// const orgs = await this.getOrgs();
|
||||||
return {
|
// return {
|
||||||
id: this.id,
|
// id: this.id,
|
||||||
username: this.username,
|
// username: this.username,
|
||||||
nickname: this.nickname,
|
// nickname: this.nickname,
|
||||||
description: this.description,
|
// description: this.description,
|
||||||
needChangePassword: this.needChangePassword,
|
// needChangePassword: this.needChangePassword,
|
||||||
type: this.type,
|
// type: this.type,
|
||||||
avatar: this.avatar,
|
// avatar: this.avatar,
|
||||||
orgs,
|
// orgs,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
async getOrgs() {
|
// async getOrgs() {
|
||||||
let id = this.id;
|
// let id = this.id;
|
||||||
if (this.type === 'org') {
|
// if (this.type === 'org') {
|
||||||
if (this.tokenUser && this.tokenUser.uid) {
|
// if (this.tokenUser && this.tokenUser.uid) {
|
||||||
id = this.tokenUser.uid;
|
// id = this.tokenUser.uid;
|
||||||
} else {
|
// } else {
|
||||||
console.log('getOrgs', 'no uid', this.id, this.username);
|
// console.log('getOrgs', 'no uid', this.id, this.username);
|
||||||
throw new CustomError('Permission denied');
|
// throw new CustomError('Permission denied');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
const cache = await redis.get(`user:${id}:orgs`);
|
// const cache = await redis.get(`user:${id}:orgs`);
|
||||||
if (cache) {
|
// if (cache) {
|
||||||
return JSON.parse(cache) as string[];
|
// return JSON.parse(cache) as string[];
|
||||||
}
|
// }
|
||||||
const orgs = await Org.findAll({
|
// const orgs = await Org.findAll({
|
||||||
order: [['updatedAt', 'DESC']],
|
// order: [['updatedAt', 'DESC']],
|
||||||
where: {
|
// where: {
|
||||||
users: {
|
// users: {
|
||||||
[Op.contains]: [
|
// [Op.contains]: [
|
||||||
{
|
// {
|
||||||
uid: id,
|
// uid: id,
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
const orgNames = orgs.map((org) => org.username);
|
// const orgNames = orgs.map((org) => org.username);
|
||||||
if (orgNames.length > 0) {
|
// if (orgNames.length > 0) {
|
||||||
await redis.set(`user:${id}:orgs`, JSON.stringify(orgNames), 'EX', 60 * 60); // 1 hour
|
// await redis.set(`user:${id}:orgs`, JSON.stringify(orgNames), 'EX', 60 * 60); // 1 hour
|
||||||
}
|
// }
|
||||||
return orgNames;
|
// return orgNames;
|
||||||
}
|
// }
|
||||||
async expireOrgs() {
|
// async expireOrgs() {
|
||||||
await redis.del(`user:${this.id}:orgs`);
|
// await redis.del(`user:${this.id}:orgs`);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
User.init(
|
// User.init(
|
||||||
{
|
// {
|
||||||
id: {
|
// id: {
|
||||||
type: DataTypes.UUID,
|
// type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
// primaryKey: true,
|
||||||
defaultValue: DataTypes.UUIDV4,
|
// defaultValue: DataTypes.UUIDV4,
|
||||||
},
|
// },
|
||||||
username: {
|
// username: {
|
||||||
type: DataTypes.STRING,
|
// type: DataTypes.STRING,
|
||||||
allowNull: false,
|
// allowNull: false,
|
||||||
unique: true,
|
// unique: true,
|
||||||
// 用户名或者手机号
|
// // 用户名或者手机号
|
||||||
// 创建后避免修改的字段,当注册用户后,用户名注册则默认不能用手机号
|
// // 创建后避免修改的字段,当注册用户后,用户名注册则默认不能用手机号
|
||||||
},
|
// },
|
||||||
nickname: {
|
// nickname: {
|
||||||
type: DataTypes.TEXT,
|
// type: DataTypes.TEXT,
|
||||||
allowNull: true,
|
// allowNull: true,
|
||||||
},
|
// },
|
||||||
alias: {
|
// alias: {
|
||||||
type: DataTypes.TEXT,
|
// type: DataTypes.TEXT,
|
||||||
allowNull: true, // 别名,网络请求的别名,需要唯一,不能和username重复
|
// allowNull: true, // 别名,网络请求的别名,需要唯一,不能和username重复
|
||||||
},
|
// defaultValue: '',
|
||||||
password: {
|
// },
|
||||||
type: DataTypes.STRING,
|
// password: {
|
||||||
allowNull: true,
|
// type: DataTypes.STRING,
|
||||||
},
|
// allowNull: true,
|
||||||
email: {
|
// },
|
||||||
type: DataTypes.STRING,
|
// email: {
|
||||||
allowNull: true,
|
// type: DataTypes.STRING,
|
||||||
},
|
// allowNull: true,
|
||||||
avatar: {
|
// },
|
||||||
type: DataTypes.TEXT,
|
// avatar: {
|
||||||
allowNull: true,
|
// type: DataTypes.TEXT,
|
||||||
},
|
// allowNull: true,
|
||||||
salt: {
|
// },
|
||||||
type: DataTypes.STRING,
|
// salt: {
|
||||||
allowNull: true,
|
// type: DataTypes.STRING,
|
||||||
},
|
// allowNull: true,
|
||||||
description: {
|
// },
|
||||||
type: DataTypes.TEXT,
|
// description: {
|
||||||
},
|
// type: DataTypes.TEXT,
|
||||||
type: {
|
// },
|
||||||
type: DataTypes.STRING,
|
// type: {
|
||||||
defaultValue: 'user',
|
// type: DataTypes.STRING,
|
||||||
},
|
// defaultValue: 'user',
|
||||||
owner: {
|
// },
|
||||||
type: DataTypes.UUID,
|
// owner: {
|
||||||
},
|
// type: DataTypes.UUID,
|
||||||
orgId: {
|
// },
|
||||||
type: DataTypes.UUID,
|
// orgId: {
|
||||||
},
|
// type: DataTypes.UUID,
|
||||||
needChangePassword: {
|
// },
|
||||||
type: DataTypes.BOOLEAN,
|
// needChangePassword: {
|
||||||
defaultValue: false,
|
// type: DataTypes.BOOLEAN,
|
||||||
},
|
// defaultValue: false,
|
||||||
data: {
|
// },
|
||||||
type: DataTypes.JSON,
|
// data: {
|
||||||
defaultValue: {},
|
// type: DataTypes.JSONB,
|
||||||
},
|
// defaultValue: {},
|
||||||
},
|
// },
|
||||||
{
|
// },
|
||||||
sequelize,
|
// {
|
||||||
tableName: 'cf_user', // codeflow user
|
// sequelize,
|
||||||
paranoid: true,
|
// tableName: 'cf_user', // codeflow user
|
||||||
},
|
// paranoid: true,
|
||||||
);
|
// },
|
||||||
User.sync({ alter: true, logging: false })
|
// );
|
||||||
.then((res) => {
|
// User.sync({ alter: true, logging: false })
|
||||||
initializeUser();
|
// .then((res) => {
|
||||||
})
|
// initializeUser();
|
||||||
.catch((err) => {
|
// })
|
||||||
console.error('Sync User error', err);
|
// .catch((err) => {
|
||||||
});
|
// console.error('Sync User error', err);
|
||||||
|
// });
|
||||||
|
|
||||||
const letter = 'abcdefghijklmnopqrstuvwxyz';
|
// const letter = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
const custom = customAlphabet(letter, 6);
|
// const custom = customAlphabet(letter, 6);
|
||||||
export const initializeUser = async (pwd = custom()) => {
|
// export const initializeUser = async (pwd = custom()) => {
|
||||||
const w = await User.findOne({ where: { username: 'root' }, logging: false });
|
// const w = await User.findOne({ where: { username: 'root' }, logging: false });
|
||||||
if (!w) {
|
// if (!w) {
|
||||||
const root = await User.createUser('root', pwd, '系统管理员');
|
// const root = await User.createUser('root', pwd, '系统管理员');
|
||||||
const org = await User.createOrg('admin', root.id, '管理员');
|
// const org = await User.createOrg('admin', root.id, '管理员');
|
||||||
console.info(' new Users name', root.username, org.username);
|
// console.info(' new Users name', root.username, org.username);
|
||||||
console.info('new Users root password', pwd);
|
// console.info('new Users root password', pwd);
|
||||||
console.info('new Users id', root.id, org.id);
|
// console.info('new Users id', root.id, org.id);
|
||||||
const demo = await createDemoUser();
|
// const demo = await createDemoUser();
|
||||||
return {
|
// return {
|
||||||
code: 200,
|
// code: 200,
|
||||||
data: { root, org, pwd: pwd, demo },
|
// data: { root, org, pwd: pwd, demo },
|
||||||
};
|
// };
|
||||||
} else {
|
// } else {
|
||||||
return {
|
// return {
|
||||||
code: 500,
|
// code: 500,
|
||||||
message: 'Users has been created',
|
// message: 'Users has been created',
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
export const createDemoUser = async (username = 'demo', pwd = custom()) => {
|
// export const createDemoUser = async (username = 'demo', pwd = custom()) => {
|
||||||
const u = await User.findOne({ where: { username }, logging: false });
|
// const u = await User.findOne({ where: { username }, logging: false });
|
||||||
if (!u) {
|
// if (!u) {
|
||||||
const user = await User.createUser(username, pwd, 'demo');
|
// const user = await User.createUser(username, pwd, 'demo');
|
||||||
console.info('new Users name', user.username, pwd);
|
// console.info('new Users name', user.username, pwd);
|
||||||
return {
|
// return {
|
||||||
code: 200,
|
// code: 200,
|
||||||
data: { user, pwd: pwd },
|
// data: { user, pwd: pwd },
|
||||||
};
|
// };
|
||||||
} else {
|
// } else {
|
||||||
console.info('Users has been created', u.username);
|
// console.info('Users has been created', u.username);
|
||||||
return {
|
// return {
|
||||||
code: 500,
|
// code: 500,
|
||||||
message: 'Users has been created',
|
// message: 'Users has been created',
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
// initializeUser();
|
// // initializeUser();
|
||||||
|
|
||||||
export class UserServices extends User {
|
// export class UserServices extends User {
|
||||||
static async loginByPhone(phone: string) {
|
// static async loginByPhone(phone: string) {
|
||||||
let user = await User.findOne({ where: { username: phone } });
|
// let user = await User.findOne({ where: { username: phone } });
|
||||||
let isNew = false;
|
// let isNew = false;
|
||||||
if (!user) {
|
// if (!user) {
|
||||||
user = await User.createUser(phone, phone.slice(-6));
|
// user = await User.createUser(phone, phone.slice(-6));
|
||||||
isNew = true;
|
// isNew = true;
|
||||||
}
|
// }
|
||||||
const token = await user.createToken(null, 'season');
|
// const token = await user.createToken(null, 'season');
|
||||||
return { ...token, isNew };
|
// return { ...token, isNew };
|
||||||
}
|
// }
|
||||||
static initializeUser = initializeUser;
|
// static initializeUser = initializeUser;
|
||||||
static createDemoUser = createDemoUser;
|
// static createDemoUser = createDemoUser;
|
||||||
}
|
// }
|
||||||
|
|
||||||
useContextKey('UserModel', () => UserServices);
|
// useContextKey('UserModel', () => UserServices);
|
||||||
|
|
||||||
|
import { User, UserServices, UserInit } from '@kevisual/code-center-module/models';
|
||||||
|
export { User, UserServices };
|
||||||
|
|
||||||
|
UserInit();
|
||||||
|
40
src/route.ts
40
src/route.ts
@ -46,6 +46,46 @@ app
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'auth-check',
|
||||||
|
key: 'admin',
|
||||||
|
id: 'check-auth-admin',
|
||||||
|
middleware: ['auth'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const tokenUser = ctx.state.tokenUser;
|
||||||
|
if (!tokenUser) {
|
||||||
|
ctx.throw(401, 'No User For authorized');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const user = await User.findOne({
|
||||||
|
where: {
|
||||||
|
id: tokenUser.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
ctx.throw(404, 'user not found');
|
||||||
|
}
|
||||||
|
user.setTokenUser(tokenUser);
|
||||||
|
const orgs = await user.getOrgs();
|
||||||
|
if (orgs.includes('admin')) {
|
||||||
|
ctx.body = 'admin';
|
||||||
|
ctx.state.tokenAdmin = {
|
||||||
|
id: user.id,
|
||||||
|
username: user.username,
|
||||||
|
orgs,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.body = 'not admin';
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`auth-admin error`, e);
|
||||||
|
console.error('tokenUser', tokenUser?.id, tokenUser?.username, tokenUser?.uid);
|
||||||
|
ctx.throw(500, e.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
app
|
app
|
||||||
.route({
|
.route({
|
||||||
|
@ -60,20 +60,11 @@ add.run = async (ctx) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await containerModel.save();
|
await containerModel.save();
|
||||||
if (containerModel.code || containerModel.source || containerModel.sourceType) {
|
|
||||||
ctx.emit?.('pageEdit', {
|
|
||||||
source: 'container',
|
|
||||||
data: containerModel.toJSON(),
|
|
||||||
operation: 'edit',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
containerModel = await ContainerModel.create({
|
containerModel = await ContainerModel.create({
|
||||||
...container,
|
...container,
|
||||||
source: '',
|
|
||||||
sourceType: '',
|
|
||||||
uid: tokenUser.id,
|
uid: tokenUser.id,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -127,25 +118,29 @@ app
|
|||||||
if (!key || !version || !fileName) {
|
if (!key || !version || !fileName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const uploadResult = await uploadMinioContainer({
|
if (container.type === 'render-js') {
|
||||||
key,
|
const uploadResult = await uploadMinioContainer({
|
||||||
tokenUser: ctx.state.tokenUser,
|
key,
|
||||||
version: version,
|
tokenUser: ctx.state.tokenUser,
|
||||||
code: container.code,
|
version: version,
|
||||||
filePath: fileName,
|
code: container.code,
|
||||||
saveHTML,
|
filePath: fileName,
|
||||||
});
|
saveHTML,
|
||||||
await ctx.call({
|
});
|
||||||
path: 'app',
|
await ctx.call({
|
||||||
key: 'uploadFiles',
|
path: 'app',
|
||||||
payload: {
|
key: 'uploadFiles',
|
||||||
token,
|
payload: {
|
||||||
data: {
|
token,
|
||||||
appKey: key,
|
data: {
|
||||||
version,
|
appKey: key,
|
||||||
files: uploadResult,
|
version,
|
||||||
|
files: uploadResult,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
} else {
|
||||||
|
ctx.throw(500, 'container type not supported:' + container.type);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
@ -16,16 +16,23 @@ export type Container = Partial<InstanceType<typeof ContainerModel>>;
|
|||||||
*/
|
*/
|
||||||
export class ContainerModel extends Model {
|
export class ContainerModel extends Model {
|
||||||
declare id: string;
|
declare id: string;
|
||||||
|
// 标题
|
||||||
declare title: string;
|
declare title: string;
|
||||||
|
// 描述
|
||||||
declare description: string;
|
declare description: string;
|
||||||
|
// 类型
|
||||||
declare type: string;
|
declare type: string;
|
||||||
|
// 标签
|
||||||
declare tags: string[];
|
declare tags: string[];
|
||||||
|
// 代码
|
||||||
declare code: string;
|
declare code: string;
|
||||||
|
// hash 值
|
||||||
declare hash: string;
|
declare hash: string;
|
||||||
declare source: string;
|
// 数据
|
||||||
declare sourceType: string;
|
|
||||||
declare data: ContainerData;
|
declare data: ContainerData;
|
||||||
|
// 发布
|
||||||
declare publish: ContainerPublish;
|
declare publish: ContainerPublish;
|
||||||
|
// 用户 id
|
||||||
declare uid: string;
|
declare uid: string;
|
||||||
declare updatedAt: Date;
|
declare updatedAt: Date;
|
||||||
declare createdAt: Date;
|
declare createdAt: Date;
|
||||||
@ -45,11 +52,11 @@ ContainerModel.init(
|
|||||||
comment: 'id',
|
comment: 'id',
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.TEXT,
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.TEXT,
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
@ -57,8 +64,8 @@ ContainerModel.init(
|
|||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING, // 代码类型, html, js, render-js
|
||||||
defaultValue: '',
|
defaultValue: 'render-js',
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
@ -68,14 +75,6 @@ ContainerModel.init(
|
|||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
},
|
},
|
||||||
source: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
sourceType: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
data: {
|
data: {
|
||||||
type: DataTypes.JSON,
|
type: DataTypes.JSON,
|
||||||
defaultValue: {},
|
defaultValue: {},
|
||||||
|
@ -8,3 +8,5 @@ import './update.ts'
|
|||||||
import './init.ts'
|
import './init.ts'
|
||||||
|
|
||||||
import './web-login.ts'
|
import './web-login.ts'
|
||||||
|
|
||||||
|
import './org-user/list.ts'
|
@ -72,6 +72,7 @@ app
|
|||||||
if (!user.checkPassword(password)) {
|
if (!user.checkPassword(password)) {
|
||||||
ctx.throw(500, 'Password error');
|
ctx.throw(500, 'Password error');
|
||||||
}
|
}
|
||||||
|
user.expireOrgs();
|
||||||
const token = await user.createToken(null, loginType);
|
const token = await user.createToken(null, loginType);
|
||||||
createCookie(token, ctx);
|
createCookie(token, ctx);
|
||||||
ctx.body = token;
|
ctx.body = token;
|
||||||
|
0
src/routes/user/org-user/index.ts
Normal file
0
src/routes/user/org-user/index.ts
Normal file
55
src/routes/user/org-user/list.ts
Normal file
55
src/routes/user/org-user/list.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { app } from '@/app.ts';
|
||||||
|
import { User } from '@/models/user.ts';
|
||||||
|
import { Org } from '@/models/org.ts';
|
||||||
|
// 获取组织的用户列表
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'org-user',
|
||||||
|
key: 'list',
|
||||||
|
middleware: ['auth'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const tokenUser = ctx.state.tokenUser;
|
||||||
|
const { orgId } = ctx.query;
|
||||||
|
const org = await Org.findByPk(orgId);
|
||||||
|
if (!org) {
|
||||||
|
ctx.throw('组织不存在');
|
||||||
|
}
|
||||||
|
// const users = await user.getUsers();
|
||||||
|
ctx.body = org;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'org-user',
|
||||||
|
key: 'operate',
|
||||||
|
middleware: ['check-auth-admin'],
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const tokenAdmin = ctx.state.tokenAdmin;
|
||||||
|
const tokenUser = ctx.state.tokenUser;
|
||||||
|
const data = ctx.query.data;
|
||||||
|
const { orgId, userId, action } = data;
|
||||||
|
const org = await Org.findByPk(orgId);
|
||||||
|
if (!org) {
|
||||||
|
ctx.throw('组织不存在');
|
||||||
|
}
|
||||||
|
const user = await User.findByPk(userId);
|
||||||
|
if (!user) {
|
||||||
|
ctx.throw('用户不存在');
|
||||||
|
}
|
||||||
|
if (user.type !== 'user') {
|
||||||
|
ctx.throw('用户类型错误');
|
||||||
|
}
|
||||||
|
const operateId = tokenUser.uid || tokenUser.id;
|
||||||
|
if (action === 'add') {
|
||||||
|
await org.addUser(user, { needPermission: true, role: 'user', operateId, isAdmin: !!tokenAdmin });
|
||||||
|
} else if (action === 'remove') {
|
||||||
|
await org.removeUser(user, { needPermission: true, operateId, isAdmin: !!tokenAdmin });
|
||||||
|
} else {
|
||||||
|
ctx.throw('操作错误');
|
||||||
|
}
|
||||||
|
ctx.body = 'ok';
|
||||||
|
})
|
||||||
|
.addTo(app);
|
@ -1,7 +1,6 @@
|
|||||||
import { app, sequelize } from '@/app.ts';
|
import { app, sequelize } from '@/app.ts';
|
||||||
import { Org } from '@/models/org.ts';
|
import { Org } from '@/models/org.ts';
|
||||||
import { User } from '@/models/user.ts';
|
import { User } from '@/models/user.ts';
|
||||||
import { CustomError } from '@kevisual/router';
|
|
||||||
import { Op } from 'sequelize';
|
import { Op } from 'sequelize';
|
||||||
|
|
||||||
app
|
app
|
||||||
@ -35,18 +34,19 @@ app
|
|||||||
.route({
|
.route({
|
||||||
path: 'org',
|
path: 'org',
|
||||||
key: 'update',
|
key: 'update',
|
||||||
middleware: ['auth'],
|
middleware: ['auth-admin'],
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const tokenUser = ctx.state.tokenUser;
|
const tokenUser = ctx.state.tokenUser;
|
||||||
|
// username 为org的名字,在用户表中也是唯一的
|
||||||
const { username, description, id } = ctx.query.data;
|
const { username, description, id } = ctx.query.data;
|
||||||
if (!username) {
|
if (!username) {
|
||||||
throw new CustomError('username is required');
|
ctx.throw('username is required');
|
||||||
}
|
}
|
||||||
if (id) {
|
if (id) {
|
||||||
const org = await Org.findByPk(id);
|
const org = await Org.findByPk(id);
|
||||||
if (!org) {
|
if (!org) {
|
||||||
throw new CustomError('org not found');
|
ctx.throw('org not found');
|
||||||
}
|
}
|
||||||
org.description = description;
|
org.description = description;
|
||||||
await org.save();
|
await org.save();
|
||||||
@ -62,11 +62,11 @@ app
|
|||||||
}
|
}
|
||||||
const user = await User.findByPk(tokenUser.id);
|
const user = await User.findByPk(tokenUser.id);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new CustomError('user not found');
|
ctx.throw('user not found');
|
||||||
}
|
}
|
||||||
const orgs = await user.getOrgs();
|
const orgs = await user.getOrgs();
|
||||||
if (!orgs.includes('admin')) {
|
if (!orgs.includes('admin')) {
|
||||||
throw new CustomError('Permission denied');
|
ctx.throw('Permission denied');
|
||||||
}
|
}
|
||||||
const newUser = await User.createOrg(username, tokenUser.id, description);
|
const newUser = await User.createOrg(username, tokenUser.id, description);
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
@ -87,17 +87,17 @@ app
|
|||||||
const tokenUser = ctx.state.tokenUser;
|
const tokenUser = ctx.state.tokenUser;
|
||||||
const id = ctx.query.id;
|
const id = ctx.query.id;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new CustomError('id is required');
|
ctx.throw('id is required');
|
||||||
}
|
}
|
||||||
const org = await Org.findByPk(id);
|
const org = await Org.findByPk(id);
|
||||||
if (!org) {
|
if (!org) {
|
||||||
throw new CustomError('org not found');
|
ctx.throw('org not found');
|
||||||
}
|
}
|
||||||
const username = org.username;
|
const username = org.username;
|
||||||
const users = org.users;
|
const users = org.users;
|
||||||
const owner = users.find((u) => u.role === 'owner');
|
const owner = users.find((u) => u.role === 'owner');
|
||||||
if (owner.uid !== tokenUser.id) {
|
if (owner.uid !== tokenUser.id) {
|
||||||
throw new CustomError('Permission denied');
|
ctx.throw('Permission denied');
|
||||||
}
|
}
|
||||||
await org.destroy({ force: true });
|
await org.destroy({ force: true });
|
||||||
const orgUser = await User.findOne({
|
const orgUser = await User.findOne({
|
||||||
@ -118,36 +118,21 @@ app
|
|||||||
const tokenUser = ctx.state.tokenUser;
|
const tokenUser = ctx.state.tokenUser;
|
||||||
const id = ctx.query.id;
|
const id = ctx.query.id;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new CustomError('id is required');
|
ctx.throw('id is required');
|
||||||
}
|
}
|
||||||
const org = await Org.findByPk(id);
|
const org = await Org.findByPk(id);
|
||||||
if (!org) {
|
if (!org) {
|
||||||
throw new CustomError('org not found');
|
ctx.throw('org not found');
|
||||||
}
|
}
|
||||||
const usersIds = org.users;
|
const usersIds = org.users;
|
||||||
const me = usersIds.find((u) => u.uid === tokenUser.id);
|
const me = usersIds.find((u) => u.uid === tokenUser.id);
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new CustomError('Permission denied');
|
ctx.throw('Permission denied');
|
||||||
}
|
}
|
||||||
const _users = await User.findAll({
|
const orgGetUser = await org.getUsers();
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: usersIds.map((u) => u.uid),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const users = _users.map((u) => {
|
|
||||||
const role = usersIds.find((r) => r.uid === u.id)?.role;
|
|
||||||
return {
|
|
||||||
id: u.id,
|
|
||||||
username: u.username,
|
|
||||||
role: role,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
org,
|
org,
|
||||||
users,
|
users: orgGetUser.users,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
21
src/scripts/container.ts
Normal file
21
src/scripts/container.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { ContainerModel } from '../routes/container/models/index.ts';
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
// await ContainerModel.update(
|
||||||
|
// {
|
||||||
|
// type: 'render-js',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// where: {
|
||||||
|
// type: '',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
const containers = await ContainerModel.findAll();
|
||||||
|
for (const container of containers) {
|
||||||
|
console.log(container.id, container.type);
|
||||||
|
}
|
||||||
|
process.exit(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
@ -4,6 +4,9 @@ import { User } from '../models/user.ts';
|
|||||||
// console.log('sync user done');
|
// console.log('sync user done');
|
||||||
// });
|
// });
|
||||||
|
|
||||||
User.findOne({ where: { username: 'admin' } }).then((user) => {
|
// class UserChange extends User {
|
||||||
console.log('user', user);
|
// static async syncUser() {
|
||||||
});
|
// await UserChange.sync({ alter: true, logging: false });
|
||||||
|
// console.log('sync user done');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user