import { useContextKey } from '@kevisual/context'; import { User } from './user.ts'; import { db } from '../../modules/db.ts'; import { cfOrgs, cfUser } from '../../db/drizzle/schema.ts'; import { eq, inArray, sql, InferSelectModel, InferInsertModel } from 'drizzle-orm'; const orgsTable = cfOrgs; const usersTable = cfUser; export enum OrgRole { admin = 'admin', member = 'member', owner = 'owner', } export type OrgUser = { role: string; uid: string; }; export type OrgSelect = InferSelectModel; export type OrgInsert = InferInsertModel; export class Org { id: string; username: string; description: string; users: OrgUser[]; constructor(data: OrgSelect) { Object.assign(this, data); } /** * 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 db.update(orgsTable).set({ users }).where(eq(orgsTable.id, this.id)); this.users = users; } /** * 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 db.update(orgsTable).set({ users }).where(eq(orgsTable.id, this.id)); this.users = users; } /** * 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 db.select().from(usersTable).where(inArray(usersTable.id, 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; } /** * 根据主键查找 */ static async findByPk(id: string): Promise { const orgs = await db.select().from(orgsTable).where(eq(orgsTable.id, id)).limit(1); return orgs.length > 0 ? new Org(orgs[0]) : null; } /** * 根据条件查找一个 */ static async findOne(where: { username?: string; id?: string }): Promise { let query = db.select().from(orgsTable); if (where.username) { query = query.where(eq(orgsTable.username, where.username)) as any; } else if (where.id) { query = query.where(eq(orgsTable.id, where.id)) as any; } const orgs = await query.limit(1); return orgs.length > 0 ? new Org(orgs[0]) : null; } /** * 创建组织 */ static async create(data: { username: string; description?: string; users: OrgUser[] }): Promise { const insertData: any = { username: data.username, users: data.users, }; if (data.description !== undefined && data.description !== null) { insertData.description = data.description; } const inserted = await db.insert(orgsTable).values(insertData).returning(); return new Org(inserted[0]); } /** * 更新组织 */ static async update(data: Partial, where: { id: string }) { await db.update(orgsTable).set(data).where(eq(orgsTable.id, where.id)); } } export const OrgModel = useContextKey('OrgModel', () => Org);