remove mark
This commit is contained in:
184
src/auth/models/org.ts
Normal file
184
src/auth/models/org.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
import { DataTypes, Model, Op, Sequelize } from 'sequelize';
|
||||
import { useContextKey } from '@kevisual/context';
|
||||
import { SyncOpts, User } from './user.ts';
|
||||
|
||||
type AddUserOpts = {
|
||||
role: string;
|
||||
};
|
||||
export enum OrgRole {
|
||||
admin = 'admin',
|
||||
member = 'member',
|
||||
owner = 'owner',
|
||||
}
|
||||
export class Org extends Model {
|
||||
declare id: string;
|
||||
declare username: string;
|
||||
declare description: string;
|
||||
declare users: { role: string; uid: string }[];
|
||||
/**
|
||||
* operateId 是真实操作者的id
|
||||
* @param user
|
||||
* @param opts
|
||||
*/
|
||||
async addUser(user: User, opts?: { operateId?: string; role: string; needPermission?: boolean; isAdmin?: boolean }) {
|
||||
const hasUser = this.users.find((u) => u.uid === user.id);
|
||||
if (hasUser) {
|
||||
return;
|
||||
}
|
||||
if (user.type !== 'user') {
|
||||
throw Error('Only user can be added to org');
|
||||
}
|
||||
if (opts?.needPermission) {
|
||||
if (opts?.isAdmin) {
|
||||
} else {
|
||||
const adminUsers = this.users.filter((u) => u.role === 'admin' || u.role === 'owner');
|
||||
const adminIds = adminUsers.map((u) => u.uid);
|
||||
const hasPermission = adminIds.includes(opts.operateId);
|
||||
if (!hasPermission) {
|
||||
throw Error('No permission');
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
await user.expireOrgs();
|
||||
} catch (e) {
|
||||
console.error('expireOrgs', e);
|
||||
}
|
||||
const users = [...this.users];
|
||||
if (opts?.role === 'owner') {
|
||||
const orgOwner = users.find((u) => u.role === 'owner');
|
||||
if (opts.isAdmin) {
|
||||
} else {
|
||||
if (!opts.operateId) {
|
||||
throw Error('operateId is required');
|
||||
}
|
||||
const owner = await User.findByPk(opts?.operateId);
|
||||
if (!owner) {
|
||||
throw Error('operateId is not found');
|
||||
}
|
||||
if (orgOwner?.uid !== owner.id) {
|
||||
throw Error('No permission');
|
||||
}
|
||||
}
|
||||
if (orgOwner) {
|
||||
orgOwner.role = 'admin';
|
||||
}
|
||||
users.push({ role: 'owner', uid: user.id });
|
||||
} else {
|
||||
users.push({ role: opts?.role || 'member', uid: user.id });
|
||||
}
|
||||
await Org.update({ users }, { where: { id: this.id } });
|
||||
|
||||
}
|
||||
/**
|
||||
* operateId 是真实操作者的id
|
||||
* @param user
|
||||
* @param opts
|
||||
*/
|
||||
async removeUser(user: User, opts?: { operateId?: string; needPermission?: boolean; isAdmin?: boolean }) {
|
||||
if (opts?.needPermission) {
|
||||
if (opts?.isAdmin) {
|
||||
} else {
|
||||
const adminUsers = this.users.filter((u) => u.role === 'admin' || u.role === 'owner');
|
||||
const adminIds = adminUsers.map((u) => u.uid);
|
||||
const hasPermission = adminIds.includes(opts.operateId);
|
||||
if (!hasPermission) {
|
||||
throw Error('No permission');
|
||||
}
|
||||
}
|
||||
}
|
||||
await user.expireOrgs();
|
||||
const users = this.users.filter((u) => u.uid !== user.id || u.role === 'owner');
|
||||
await Org.update({ users }, { where: { id: this.id } });
|
||||
}
|
||||
/**
|
||||
* operateId 是真实操作者的id
|
||||
* @param user
|
||||
* @param opts
|
||||
*/
|
||||
async getUsers(opts?: { operateId: string; needPermission?: boolean; isAdmin?: boolean }) {
|
||||
const usersIds = this.users.map((u) => u.uid);
|
||||
const orgUser = this.users;
|
||||
if (opts?.needPermission) {
|
||||
// 不在组织内或者不是管理员,如果需要权限,返回空
|
||||
if (opts.isAdmin) {
|
||||
} else {
|
||||
const hasPermission = usersIds.includes(opts.operateId);
|
||||
if (!hasPermission) {
|
||||
return {
|
||||
hasPermission: false,
|
||||
users: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
const _users = await User.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Op.in]: usersIds,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const users = _users.map((u) => {
|
||||
const role = orgUser.find((r) => r.uid === u.id)?.role;
|
||||
return {
|
||||
id: u.id,
|
||||
username: u.username,
|
||||
role: role,
|
||||
};
|
||||
});
|
||||
return { users };
|
||||
}
|
||||
/**
|
||||
* 检测用户是否在组织内,且角色为role
|
||||
* @param user
|
||||
* @param opts
|
||||
*/
|
||||
async getInRole(userId: string, role = 'admin') {
|
||||
const user = this.users.find((u) => u.uid === userId && u.role === role);
|
||||
return !!user;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 组织模型,在sequelize之后初始化
|
||||
*/
|
||||
export const OrgInit = async (newSequelize?: any, tableName?: string, sync?: SyncOpts) => {
|
||||
const sequelize = useContextKey<Sequelize>('sequelize');
|
||||
Org.init(
|
||||
{
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
primaryKey: true,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
},
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
},
|
||||
description: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
users: {
|
||||
type: DataTypes.JSONB,
|
||||
allowNull: true,
|
||||
defaultValue: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize: newSequelize || sequelize,
|
||||
modelName: tableName || 'cf_org',
|
||||
paranoid: true,
|
||||
},
|
||||
);
|
||||
if (sync) {
|
||||
await Org.sync({ alter: true, logging: false, ...sync }).catch((e) => {
|
||||
console.error('Org sync', e);
|
||||
});
|
||||
return Org;
|
||||
}
|
||||
return Org;
|
||||
};
|
||||
export const OrgModel = useContextKey('OrgModel', () => Org);
|
||||
Reference in New Issue
Block a user