/** * Supabase 消息系统客户端 - 完整角色管理版本 * 包含角色管理、权限检查、消息操作等功能 */ import { createClient } from '@supabase/supabase-js' // Supabase 配置 const supabaseUrl = 'YOUR_SUPABASE_URL' const supabaseKey = 'YOUR_SUPABASE_ANON_KEY' const supabase = createClient(supabaseUrl, supabaseKey) /** * 用户角色管理类 */ class UserRoleManager { constructor(supabaseClient) { this.supabase = supabaseClient this.currentUser = null this.currentRole = null this.permissions = {} } /** * 初始化用户角色信息 */ async initialize() { try { const { data: { user } } = await this.supabase.auth.getUser() if (user) { this.currentUser = user this.currentRole = await this.getUserRole(user.id) this.permissions = await this.getUserPermissions(user.id) console.log('✅ 用户角色初始化完成:', { userId: user.id, email: user.email, role: this.currentRole, permissions: this.permissions }) } return { user: this.currentUser, role: this.currentRole, permissions: this.permissions } } catch (error) { console.error('❌ 用户角色初始化失败:', error) throw error } } /** * 获取用户角色 * @param {string} userId - 用户ID * @returns {Promise} 用户角色 */ async getUserRole(userId = null) { try { const { data, error } = await this.supabase .rpc('get_user_role', { target_user_id: userId }) if (error) throw error return data || 'student' } catch (error) { console.error('获取用户角色失败:', error) return 'student' } } /** * 获取用户权限 * @param {string} userId - 用户ID * @returns {Promise} 用户权限对象 */ async getUserPermissions(userId = null) { try { const { data, error } = await this.supabase .from('user_roles') .select('permissions') .eq('user_id', userId || this.currentUser?.id) .eq('is_active', true) .single() if (error && error.code !== 'PGRST116') throw error return data?.permissions || {} } catch (error) { console.error('获取用户权限失败:', error) return {} } } /** * 检查用户是否有特定权限 * @param {string} permission - 权限名称 * @param {string} userId - 用户ID(可选) * @returns {Promise} 是否有权限 */ async hasPermission(permission, userId = null) { try { const { data, error } = await this.supabase .rpc('user_has_permission', { permission_name: permission, target_user_id: userId }) if (error) throw error return data === true } catch (error) { console.error('权限检查失败:', error) return false } } /** * 检查是否可以访问资源 * @param {string} resourceType - 资源类型 * @param {string} resourceId - 资源ID * @param {string} accessType - 访问类型 * @returns {Promise} 是否可以访问 */ async canAccessResource(resourceType, resourceId, accessType = 'read') { try { const { data, error } = await this.supabase .rpc('can_access_resource', { resource_type: resourceType, resource_id: resourceId, access_type: accessType }) if (error) throw error return data === true } catch (error) { console.error('资源访问检查失败:', error) return false } } /** * 更新用户角色(仅管理员) * @param {string} targetUserId - 目标用户ID * @param {string} newRole - 新角色 * @param {Object} additionalData - 额外数据 * @returns {Promise} 是否更新成功 */ async updateUserRole(targetUserId, newRole, additionalData = {}) { try { const { data, error } = await this.supabase .rpc('update_user_role', { target_user_id: targetUserId, new_role: newRole, additional_data: additionalData }) if (error) throw error console.log('✅ 用户角色更新成功:', { targetUserId, newRole }) return data === true } catch (error) { console.error('❌ 用户角色更新失败:', error) throw error } } /** * 批量更新用户角色 * @param {Array} roleUpdates - 角色更新数组 * @returns {Promise} 更新结果 */ async batchUpdateUserRoles(roleUpdates) { try { const { data, error } = await this.supabase .rpc('batch_update_user_roles', { role_updates: roleUpdates }) if (error) throw error console.log('✅ 批量角色更新完成:', data) return data } catch (error) { console.error('❌ 批量角色更新失败:', error) throw error } } /** * 获取用户详细信息(管理员视图) */ async getUsersWithRoles() { try { const { data, error } = await this.supabase .from('user_roles_detailed') .select('*') .order('created_at', { ascending: false }) if (error) throw error return data } catch (error) { console.error('获取用户角色列表失败:', error) throw error } } /** * 测试权限系统 * @param {string} testUserId - 测试用户ID */ async testPermissions(testUserId = null) { try { const { data, error } = await this.supabase .rpc('test_message_permissions', { test_user_id: testUserId || this.currentUser?.id }) if (error) throw error console.log('🧪 权限测试结果:', data) return data } catch (error) { console.error('权限测试失败:', error) throw error } } } /** * 消息系统管理类 */ class MessageManager { constructor(supabaseClient, roleManager) { this.supabase = supabaseClient this.roleManager = roleManager } /** * 发送安全消息 * @param {Object} messageData - 消息数据 * @returns {Promise} 消息ID */ async sendSecureMessage(messageData) { try { const { messageTypeId, receiverType, receiverId, title, content, metadata = {} } = messageData const { data, error } = await this.supabase .rpc('send_secure_message', { message_type_id: messageTypeId, receiver_type: receiverType, receiver_id: receiverId, title, content, metadata_json: metadata }) if (error) throw error console.log('✅ 消息发送成功:', data) return data } catch (error) { console.error('❌ 消息发送失败:', error) throw error } } /** * 获取用户可访问的消息列表 * @param {Object} options - 查询选项 * @returns {Promise} 消息列表 */ async getAccessibleMessages(options = {}) { try { const { limit = 50, offset = 0, messageType = null, unreadOnly = false } = options let query = this.supabase .from('ak_messages') .select(` *, ak_message_types(type_name, display_name), ak_message_recipients( read_at, replied_at, status ) `) .order('created_at', { ascending: false }) .range(offset, offset + limit - 1) if (messageType) { query = query.eq('ak_message_types.type_name', messageType) } if (unreadOnly) { query = query.is('ak_message_recipients.read_at', null) } const { data, error } = await query if (error) throw error return data } catch (error) { console.error('获取消息列表失败:', error) throw error } } /** * 标记消息为已读 * @param {string} messageId - 消息ID */ async markMessageAsRead(messageId) { try { const { error } = await this.supabase .from('ak_message_recipients') .update({ read_at: new Date().toISOString(), status: 'read' }) .eq('message_id', messageId) .eq('user_id', this.roleManager.currentUser?.id) if (error) throw error console.log('✅ 消息已标记为已读:', messageId) } catch (error) { console.error('标记消息已读失败:', error) throw error } } /** * 获取消息统计 */ async getMessageStats() { try { const { data, error } = await this.supabase .from('ak_message_stats') .select('*') .eq('entity_type', 'user') .eq('entity_id', this.roleManager.currentUser?.id) if (error) throw error return data } catch (error) { console.error('获取消息统计失败:', error) throw error } } /** * 加入消息群组 * @param {string} groupId - 群组ID * @param {string} joinMessage - 加入消息 */ async joinMessageGroup(groupId, joinMessage = '') { try { const { data, error } = await this.supabase .rpc('join_message_group', { target_group_id: groupId, join_message: joinMessage }) if (error) throw error if (data === true) { console.log('✅ 成功加入群组:', groupId) } else { console.log('⏳ 申请已提交,等待审批:', groupId) } return data } catch (error) { console.error('加入群组失败:', error) throw error } } /** * 获取用户可访问的群组列表 */ async getAccessibleGroups() { try { const { data, error } = await this.supabase .from('ak_message_groups') .select(` *, ak_message_group_members!inner( status, joined_at, role ) `) .eq('ak_message_group_members.user_id', this.roleManager.currentUser?.id) .eq('ak_message_group_members.status', 'active') .order('created_at', { ascending: false }) if (error) throw error return data } catch (error) { console.error('获取群组列表失败:', error) throw error } } } /** * 主应用类 */ class MessageApp { constructor() { this.supabase = supabase this.roleManager = new UserRoleManager(this.supabase) this.messageManager = new MessageManager(this.supabase, this.roleManager) this.initialized = false } /** * 初始化应用 */ async initialize() { try { await this.roleManager.initialize() this.initialized = true // 监听认证状态变化 this.supabase.auth.onAuthStateChange(async (event, session) => { console.log('🔄 认证状态变化:', event) if (event === 'SIGNED_IN' || event === 'TOKEN_REFRESHED') { await this.roleManager.initialize() } else if (event === 'SIGNED_OUT') { this.roleManager.currentUser = null this.roleManager.currentRole = null this.roleManager.permissions = {} } }) console.log('✅ 消息应用初始化完成') return true } catch (error) { console.error('❌ 消息应用初始化失败:', error) throw error } } /** * 用户登录 * @param {string} email - 邮箱 * @param {string} password - 密码 */ async signIn(email, password) { try { const { data, error } = await this.supabase.auth.signInWithPassword({ email, password }) if (error) throw error await this.roleManager.initialize() console.log('✅ 登录成功') return data } catch (error) { console.error('❌ 登录失败:', error) throw error } } /** * 用户注册 * @param {string} email - 邮箱 * @param {string} password - 密码 * @param {Object} metadata - 额外元数据 */ async signUp(email, password, metadata = {}) { try { const { data, error } = await this.supabase.auth.signUp({ email, password, options: { data: metadata } }) if (error) throw error console.log('✅ 注册成功,请检查邮箱验证') return data } catch (error) { console.error('❌ 注册失败:', error) throw error } } /** * 用户退出 */ async signOut() { try { const { error } = await this.supabase.auth.signOut() if (error) throw error console.log('✅ 退出成功') } catch (error) { console.error('❌ 退出失败:', error) throw error } } /** * 获取当前用户信息 */ getCurrentUserInfo() { return { user: this.roleManager.currentUser, role: this.roleManager.currentRole, permissions: this.roleManager.permissions, initialized: this.initialized } } /** * 角色管理器 */ get roles() { return this.roleManager } /** * 消息管理器 */ get messages() { return this.messageManager } } // 创建全局实例 const messageApp = new MessageApp() // 导出 export { MessageApp, UserRoleManager, MessageManager, messageApp } // 使用示例 /* // 1. 初始化应用 await messageApp.initialize() // 2. 用户登录 await messageApp.signIn('teacher@example.com', 'password123') // 3. 检查用户角色和权限 const userInfo = messageApp.getCurrentUserInfo() console.log('当前用户:', userInfo) // 4. 检查特定权限 const canSendBroadcast = await messageApp.roles.hasPermission('can_send_broadcasts') console.log('可以发送广播:', canSendBroadcast) // 5. 发送消息 const messageId = await messageApp.messages.sendSecureMessage({ messageTypeId: 'some-type-id', receiverType: 'user', receiverId: 'student-user-id', title: '作业通知', content: '请完成本周的作业', metadata: { priority: 'high' } }) // 6. 获取消息列表 const messages = await messageApp.messages.getAccessibleMessages({ limit: 20, unreadOnly: true }) // 7. 加入群组 const joinResult = await messageApp.messages.joinMessageGroup('group-id') // 8. 管理员操作:更新用户角色 if (userInfo.role === 'admin') { await messageApp.roles.updateUserRole('user-id', 'teacher', { department: 'Mathematics', class_id: 'class-123' }) } // 9. 测试权限系统 await messageApp.roles.testPermissions() */