Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,609 @@
/**
* 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<string>} 用户角色
*/
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<Object>} 用户权限对象
*/
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<boolean>} 是否有权限
*/
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<boolean>} 是否可以访问
*/
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<boolean>} 是否更新成功
*/
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<Array>} 更新结果
*/
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<string>} 消息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<Array>} 消息列表
*/
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()
*/