blob: 2ffffbc378322fab64367055661ab93314291ce1 [file] [log] [blame]
from models.user import User as users
from models.post import Post as post
import secrets
import hashlib
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from models.logs import Log
from models.syscost import PerformanceData
import os
import requests
from werkzeug.utils import secure_filename
import uuid
class Fpost:
def __init__(self,session:Session):
self.session=session
# 配置文件存储节点(docker容器的实际路径)
self.storage_nodes = [
'/home/tianruiming/docker02/static',
'/home/tianruiming/docker03/static',
'/home/tianruiming/docker04/static'
]
# 默认访问节点(LVS负载均衡器)
self.access_node = '192.168.5.200:8080'
return
def getlist(self):
results = self.session.query(post.id, post.title,post.status)
return results
def getuserlist(self):
results= self.session.query(users.id, users.username, users.role)
return results
def giveadmin(self,userid):
res=self.session.query(users).filter(users.id==userid).first()
if not res:
return False
res.role='admin'
self.session.commit()
return True
def giveuser(self,userid):
res=self.session.query(users).filter(users.id==userid).first()
if not res:
return False
res.role='user'
self.session.commit()
return True
def givesuperadmin(self,userid):
res=self.session.query(users).filter(users.id==userid).first()
if not res:
return False
res.role='superadmin'
self.session.commit()
return True
def getpost(self,postid):
res=self.session.query(post).filter(post.id==postid).first()
return res
def checkid(self,userid,status=''):
res=self.session.query(users).filter(users.id==userid).first()
if(not res):
return False
if res.role !=status:
return False
return True
def review(self,postid,status):
print(status)
res=self.session.query(post).filter(post.id==postid).first()
if not res:
return False
res.status=status
self.session.commit()
return True
def createtoken(self, userid):
"""
根据userid创建token并插入到数据库
:param userid: 用户ID
:return: 生成的token字符串
"""
# 生成随机盐值
salt = secrets.token_hex(16)
# 创建哈希值:userid + 当前时间戳 + 随机盐值
current_time = str(datetime.now().timestamp())
hash_input = f"{userid}_{current_time}_{salt}"
# 生成SHA256哈希值作为token
token = hashlib.sha256(hash_input.encode()).hexdigest()
# 设置时间
created_time = datetime.now()
expires_time = created_time + timedelta(days=1) # 一天后过期
try:
# 创建新的token记录
new_token = Token(
token=token,
expires_at=expires_time,
created_at=created_time
)
# 假设self.session是数据库会话对象
self.session.add(new_token)
self.session.commit()
return token
except Exception as e:
self.session.rollback()
raise Exception(f"创建token失败: {str(e)}")
def recordlog(self,user_id,log_type,content,ip):
"""
记录日志
:param user_id: 用户ID
:param log_type: 日志类型,'access','error','behavior','system'
:param content: 日志内容
:param ip: IP地址
"""
try:
new_log = Log(
user_id=user_id,
type=log_type,
content=content,
ip=ip
)
self.session.add(new_log)
self.session.commit()
except Exception as e:
self.session.rollback()
raise Exception(f"记录日志失败: {str(e)}")
def getrecordlog(self):
res= self.session.query(Log).all()
return res
def recordsyscost(self, endpoint: str, elapsed_time: float, cpu_user: float, cpu_system: float, memory_rss: int):
"""
记录系统性能消耗到 performance_data 表
:param endpoint: 请求接口路径
:param elapsed_time: 总耗时(秒)
:param cpu_user: 用户态 CPU 时间差(秒)
:param cpu_system: 系统态 CPU 时间差(秒)
:param memory_rss: RSS 内存增量(字节)
"""
try:
new_record = PerformanceData(
endpoint=endpoint,
elapsed_time=elapsed_time,
cpu_user=cpu_user,
cpu_system=cpu_system,
memory_rss=memory_rss
)
self.session.add(new_record)
self.session.commit()
except Exception as e:
self.session.rollback()
raise Exception(f"记录系统性能消耗失败: {e}")
def getsyscost(self):
res= self.session.query(PerformanceData).all()
return res
def save_files_to_storage(self, files, post_id):
"""
将文件保存到所有存储节点
:param files: 文件列表
:param post_id: 帖子ID
:return: 媒体URL列表
"""
media_urls = []
for file in files:
if file and file.filename:
# 生成安全的文件名
original_filename = secure_filename(file.filename)
# 生成唯一文件名避免冲突
unique_id = str(uuid.uuid4())
file_extension = os.path.splitext(original_filename)[1]
unique_filename = f"{unique_id}{file_extension}"
# 读取文件内容
file_content = file.read()
file.seek(0) # 重置文件指针
# 保存到所有存储节点
success_count = 0
for node_path in self.storage_nodes:
try:
# 创建目录路径:/home/tianruiming/docker0X/static/{post_id}/
node_dir = os.path.join(node_path, str(post_id))
os.makedirs(node_dir, exist_ok=True)
# 完整文件路径
full_file_path = os.path.join(node_dir, unique_filename)
# 写入文件到存储节点
with open(full_file_path, 'wb') as f:
f.write(file_content)
success_count += 1
print(f"Successfully saved file to {full_file_path}")
except Exception as e:
print(f"Failed to save file to node {node_path}: {str(e)}")
if success_count > 0:
# 生成访问URL,格式:http://192.168.5.231:8080/static/{post_id}/{filename}
media_url = f"http://{self.access_node}/static/{post_id}/{unique_filename}"
media_urls.append(media_url)
else:
raise Exception(f"Failed to save file {original_filename} to any storage node")
return media_urls
def create_post_with_files(self, user_id, title, content, topic_id, status, files):
"""
创建带文件的帖子
:param user_id: 用户ID
:param title: 标题
:param content: 内容
:param topic_id: 话题ID
:param status: 状态
:param files: 文件列表
:return: 帖子对象
"""
# 先创建帖子获取ID
new_post = post(
user_id=user_id,
title=title,
content=content,
topic_id=topic_id if topic_id else None,
status=status,
created_at=datetime.now(),
updated_at=datetime.now()
)
self.session.add(new_post)
self.session.flush() # 获取ID但不提交
# 保存文件
if files:
media_urls = self.save_files_to_storage(files, new_post.id)
new_post.media_urls = media_urls
else:
new_post.media_urls = []
self.session.commit()
return new_post
def update_post_with_files(self, post_id, title=None, content=None, topic_id=None, status=None, files=None, existing_media_urls=None):
"""
更新带文件的帖子
:param post_id: 帖子ID
:param title: 标题
:param content: 内容
:param topic_id: 话题ID
:param status: 状态
:param files: 新文件列表
:param existing_media_urls: 现有媒体URL
:return: 更新后的帖子对象
"""
post_obj = self.session.query(post).filter(post.id == post_id).first()
if not post_obj:
return None
# 更新基本信息
if title is not None:
post_obj.title = title
if content is not None:
post_obj.content = content
if topic_id is not None:
post_obj.topic_id = topic_id
if status is not None:
post_obj.status = status
post_obj.updated_at = datetime.now()
# 处理文件
if files:
# 有新文件,保存新文件
media_urls = self.save_files_to_storage(files, post_id)
post_obj.media_urls = media_urls
elif existing_media_urls is not None:
# 保留现有媒体URL
post_obj.media_urls = existing_media_urls
self.session.commit()
return post_obj