增加了会议访问密码

main
mula.liu 2025-12-16 18:55:31 +08:00
parent de289add81
commit 85d16a60da
7 changed files with 174 additions and 8 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
app.zip

Binary file not shown.

View File

@ -232,7 +232,8 @@ def get_meeting_details(meeting_id: int, current_user: dict = Depends(get_curren
cursor = connection.cursor(dictionary=True)
query = '''
SELECT m.meeting_id, m.title, m.meeting_time, m.summary, m.created_at, m.tags,
m.user_id as creator_id, u.caption as creator_username, af.file_path as audio_file_path
m.user_id as creator_id, u.caption as creator_username, af.file_path as audio_file_path,
m.access_password
FROM meetings m JOIN users u ON m.user_id = u.user_id LEFT JOIN audio_files af ON m.meeting_id = af.meeting_id
WHERE m.meeting_id = %s
'''
@ -249,7 +250,8 @@ def get_meeting_details(meeting_id: int, current_user: dict = Depends(get_curren
meeting_data = Meeting(
meeting_id=meeting['meeting_id'], title=meeting['title'], meeting_time=meeting['meeting_time'],
summary=meeting['summary'], created_at=meeting['created_at'], attendees=attendees,
creator_id=meeting['creator_id'], creator_username=meeting['creator_username'], tags=tags
creator_id=meeting['creator_id'], creator_username=meeting['creator_username'], tags=tags,
access_password=meeting.get('access_password')
)
if meeting['audio_file_path']:
meeting_data.audio_file_path = meeting['audio_file_path']
@ -341,7 +343,8 @@ def get_meeting_for_edit(meeting_id: int, current_user: dict = Depends(get_curre
cursor = connection.cursor(dictionary=True)
query = '''
SELECT m.meeting_id, m.title, m.meeting_time, m.summary, m.created_at, m.tags,
m.user_id as creator_id, u.caption as creator_username, af.file_path as audio_file_path
m.user_id as creator_id, u.caption as creator_username, af.file_path as audio_file_path,
m.access_password
FROM meetings m JOIN users u ON m.user_id = u.user_id LEFT JOIN audio_files af ON m.meeting_id = af.meeting_id
WHERE m.meeting_id = %s
'''
@ -358,7 +361,8 @@ def get_meeting_for_edit(meeting_id: int, current_user: dict = Depends(get_curre
meeting_data = Meeting(
meeting_id=meeting['meeting_id'], title=meeting['title'], meeting_time=meeting['meeting_time'],
summary=meeting['summary'], created_at=meeting['created_at'], attendees=attendees,
creator_id=meeting['creator_id'], creator_username=meeting['creator_username'], tags=tags
creator_id=meeting['creator_id'], creator_username=meeting['creator_username'], tags=tags,
access_password=meeting.get('access_password')
)
if meeting.get('audio_file_path'):
meeting_data.audio_file_path = meeting['audio_file_path']
@ -888,7 +892,7 @@ def get_meeting_preview_data(meeting_id: int):
query = '''
SELECT m.meeting_id, m.title, m.meeting_time, m.summary, m.updated_at, m.prompt_id,
m.user_id as creator_id, u.caption as creator_username,
p.name as prompt_name
p.name as prompt_name, m.access_password
FROM meetings m
JOIN users u ON m.user_id = u.user_id
LEFT JOIN prompts p ON m.prompt_id = p.id
@ -920,10 +924,136 @@ def get_meeting_preview_data(meeting_id: int):
"prompt_id": meeting['prompt_id'],
"prompt_name": meeting['prompt_name'],
"attendees": attendees,
"attendees_count": len(attendees)
"attendees_count": len(attendees),
"has_password": bool(meeting.get('access_password')) # 新增:是否设置了访问密码
}
return create_api_response(code="200", message="获取会议预览数据成功", data=preview_data)
except Exception as e:
return create_api_response(code="500", message=f"Failed to get meeting preview data: {str(e)}")
# 访问密码管理相关API
class AccessPasswordRequest(BaseModel):
password: Optional[str] = None # None表示关闭密码
class VerifyPasswordRequest(BaseModel):
password: str
@router.put("/meetings/{meeting_id}/access-password")
def update_meeting_access_password(
meeting_id: int,
request: AccessPasswordRequest,
current_user: dict = Depends(get_current_user)
):
"""
设置或关闭会议访问密码仅创建人可操作
Args:
meeting_id: 会议ID
request.password: 密码字符串None表示关闭密码
current_user: 当前登录用户
Returns:
API响应包含操作结果
"""
try:
with get_db_connection() as connection:
cursor = connection.cursor(dictionary=True)
# 检查会议是否存在且当前用户是创建人
cursor.execute(
"SELECT meeting_id, user_id FROM meetings WHERE meeting_id = %s",
(meeting_id,)
)
meeting = cursor.fetchone()
if not meeting:
return create_api_response(code="404", message="会议不存在")
if meeting['user_id'] != current_user['user_id']:
return create_api_response(code="403", message="仅创建人可以设置访问密码")
# 更新访问密码
cursor.execute(
"UPDATE meetings SET access_password = %s WHERE meeting_id = %s",
(request.password, meeting_id)
)
connection.commit()
if request.password:
return create_api_response(
code="200",
message="访问密码已设置",
data={"password": request.password}
)
else:
return create_api_response(
code="200",
message="访问密码已关闭",
data={"password": None}
)
except Exception as e:
return create_api_response(
code="500",
message=f"设置访问密码失败: {str(e)}"
)
@router.post("/meetings/{meeting_id}/verify-password")
def verify_meeting_password(meeting_id: int, request: VerifyPasswordRequest):
"""
验证会议访问密码无需登录认证
Args:
meeting_id: 会议ID
request.password: 要验证的密码
Returns:
API响应包含验证结果
"""
try:
with get_db_connection() as connection:
cursor = connection.cursor(dictionary=True)
# 获取会议的访问密码
cursor.execute(
"SELECT access_password FROM meetings WHERE meeting_id = %s",
(meeting_id,)
)
meeting = cursor.fetchone()
if not meeting:
return create_api_response(code="404", message="会议不存在")
# 验证密码
stored_password = meeting.get('access_password')
if not stored_password:
# 没有设置密码,直接通过
return create_api_response(
code="200",
message="该会议未设置访问密码",
data={"verified": True}
)
if request.password == stored_password:
return create_api_response(
code="200",
message="密码验证成功",
data={"verified": True}
)
else:
return create_api_response(
code="200",
message="密码错误",
data={"verified": False}
)
except Exception as e:
return create_api_response(
code="500",
message=f"验证密码失败: {str(e)}"
)

View File

@ -203,6 +203,37 @@ def delete_prompt(prompt_id: int, current_user: dict = Depends(get_current_user)
if prompt['creator_id'] != current_user["user_id"]:
return create_api_response(code="403", message="无权删除其他用户的提示词")
# 检查是否有会议引用了该提示词
cursor.execute(
"SELECT COUNT(*) as count FROM meetings WHERE prompt_id = %s",
(prompt_id,)
)
meeting_count = cursor.fetchone()['count']
# 检查是否有知识库引用了该提示词
cursor.execute(
"SELECT COUNT(*) as count FROM knowledge_bases WHERE prompt_id = %s",
(prompt_id,)
)
kb_count = cursor.fetchone()['count']
# 如果有引用,不允许删除
if meeting_count > 0 or kb_count > 0:
references = []
if meeting_count > 0:
references.append(f"{meeting_count}个会议")
if kb_count > 0:
references.append(f"{kb_count}个知识库")
return create_api_response(
code="400",
message=f"无法删除:该提示词被{''.join(references)}引用",
data={
"meeting_count": meeting_count,
"kb_count": kb_count
}
)
# 删除提示词
cursor.execute("DELETE FROM prompts WHERE id = %s", (prompt_id,))
connection.commit()

View File

@ -77,6 +77,7 @@ class Meeting(BaseModel):
audio_file_path: Optional[str] = None
transcription_status: Optional[TranscriptionTaskStatus] = None
tags: Optional[List[Tag]] = []
access_password: Optional[str] = None
class TranscriptSegment(BaseModel):
segment_id: int

View File

@ -14,4 +14,7 @@ qiniu
# Validation & Forms
email-validator
python-multipart
python-multipart
# System Monitoring
psutil

View File

@ -8,4 +8,5 @@ qiniu
redis>=5.0.0
dashscope
PyJWT>=2.8.0
python-jose[cryptography]>=3.3.0
python-jose[cryptography]>=3.3.0
psutil