582 lines
23 KiB
Python
582 lines
23 KiB
Python
|
|
import time
|
|||
|
|
from app.views.ViewsBase import *
|
|||
|
|
from app.utils.Utils import buildPageLabels
|
|||
|
|
from django.shortcuts import render, redirect
|
|||
|
|
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
|
|||
|
|
from django.contrib.auth.models import Group, User
|
|||
|
|
from app.utils.Credentials import redact_mapping
|
|||
|
|
from app.utils.OSSystem import OSSystem
|
|||
|
|
from io import BytesIO
|
|||
|
|
from app.utils.LogUtils import LogUtils
|
|||
|
|
from django.http import HttpResponse
|
|||
|
|
import json
|
|||
|
|
# 生成验证码start
|
|||
|
|
import random
|
|||
|
|
from PIL import Image, ImageDraw, ImageFont
|
|||
|
|
|
|||
|
|
def random_color(min_val=50, max_val=200):
|
|||
|
|
"""生成随机RGB颜色"""
|
|||
|
|
return (
|
|||
|
|
random.randint(min_val, max_val),
|
|||
|
|
random.randint(min_val, max_val),
|
|||
|
|
random.randint(min_val, max_val)
|
|||
|
|
)
|
|||
|
|
def load_captcha_font(height):
|
|||
|
|
"""跨平台字体加载(优先Linux兼容字体)"""
|
|||
|
|
osSystem = OSSystem()
|
|||
|
|
if osSystem.getSystemName() == "Windows":
|
|||
|
|
font_paths = [
|
|||
|
|
g_config.fontPath, # 项目内嵌字体
|
|||
|
|
"C:\\Windows\\Fonts\\arial.ttf" # Windows
|
|||
|
|
]
|
|||
|
|
else:
|
|||
|
|
font_paths = [
|
|||
|
|
g_config.fontPath, # 项目内嵌字体
|
|||
|
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" # Linux
|
|||
|
|
]
|
|||
|
|
for font_path in font_paths:
|
|||
|
|
try:
|
|||
|
|
if os.path.exists(font_path):
|
|||
|
|
font_size = int(height * 0.7)
|
|||
|
|
font = ImageFont.truetype(font_path, font_size)
|
|||
|
|
return font,font_size
|
|||
|
|
else:
|
|||
|
|
raise Exception("file not exist")
|
|||
|
|
except Exception as e:
|
|||
|
|
g_logger.error("load_captcha_font() error,font_path=%s,e=%s"%(font_path,str(e)))
|
|||
|
|
|
|||
|
|
font_size = int(height * 2)
|
|||
|
|
return ImageFont.load_default(),font_size # 保底方案
|
|||
|
|
def generate_secure_captcha(length=4):
|
|||
|
|
"""生成带干扰线的验证码图片"""
|
|||
|
|
|
|||
|
|
width = 120
|
|||
|
|
height = 40
|
|||
|
|
font,font_size = load_captcha_font(height)
|
|||
|
|
|
|||
|
|
image = Image.new('RGB', (width, height), (255, 255, 255))
|
|||
|
|
draw = ImageDraw.Draw(image)
|
|||
|
|
|
|||
|
|
# 生成随机文本(排除易混淆字符)
|
|||
|
|
chars = 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'
|
|||
|
|
captcha_text = ''.join(random.choices(chars, k=length))
|
|||
|
|
|
|||
|
|
# 绘制扭曲字符
|
|||
|
|
x_offset = 10
|
|||
|
|
for char in captcha_text:
|
|||
|
|
angle = random.randint(-10, 10) # 随机旋转角度
|
|||
|
|
char_img = Image.new('RGBA', (font_size, font_size), (0, 0, 0, 0))
|
|||
|
|
char_draw = ImageDraw.Draw(char_img)
|
|||
|
|
char_draw.text((0, 0), char, font=font, fill=random_color(0, 100))
|
|||
|
|
rotated_char = char_img.rotate(angle, expand=True, resample=Image.BILINEAR)
|
|||
|
|
image.paste(rotated_char, (x_offset, 5), rotated_char)
|
|||
|
|
x_offset += rotated_char.width - random.randint(0, 8) # 随机间距
|
|||
|
|
|
|||
|
|
# 添加干扰线(核心防御)
|
|||
|
|
for _ in range(4): # 干扰线数量
|
|||
|
|
x1, y1 = random.randint(0, width), random.randint(0, height)
|
|||
|
|
x2, y2 = random.randint(0, width), random.randint(0, height)
|
|||
|
|
draw.line([x1, y1, x2, y2], fill=random_color(150, 220), width=random.choice([1, 2]))
|
|||
|
|
|
|||
|
|
# 添加噪点(30个点)
|
|||
|
|
for _ in range(30):
|
|||
|
|
x, y = random.randint(0, width), random.randint(0, height)
|
|||
|
|
draw.point((x, y), fill=random_color(100, 200))
|
|||
|
|
|
|||
|
|
return captcha_text, image
|
|||
|
|
# 生成验证码end
|
|||
|
|
|
|||
|
|
|
|||
|
|
def index(request):
|
|||
|
|
context = {}
|
|||
|
|
return render(request, 'app/user/index.html', context)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def api_openIndex(request):
|
|||
|
|
ret = False
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
data = []
|
|||
|
|
pageData = {}
|
|||
|
|
|
|||
|
|
if request.method == 'GET':
|
|||
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|||
|
|
if __check_ret:
|
|||
|
|
params = f_parseGetParams(request)
|
|||
|
|
|
|||
|
|
page = params.get('p', 1)
|
|||
|
|
page_size = params.get('ps', 10)
|
|||
|
|
try:
|
|||
|
|
page = int(page)
|
|||
|
|
except:
|
|||
|
|
page = 1
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
page_size = int(page_size)
|
|||
|
|
if page_size < 1:
|
|||
|
|
page_size = 1
|
|||
|
|
except:
|
|||
|
|
page_size = 10
|
|||
|
|
|
|||
|
|
skip = (page - 1) * page_size
|
|||
|
|
sql_data = ("select id,username,email,is_active,is_superuser,is_staff,date_joined,last_login "
|
|||
|
|
"from auth_user order by id desc limit %s,%s")
|
|||
|
|
sql_data_num = "select count(id) as count from auth_user "
|
|||
|
|
|
|||
|
|
count = g_database.select(sql_data_num)
|
|||
|
|
|
|||
|
|
if len(count) > 0:
|
|||
|
|
count = int(count[0]["count"])
|
|||
|
|
data = g_database.select(sql_data, [skip, page_size])
|
|||
|
|
else:
|
|||
|
|
count = 0
|
|||
|
|
|
|||
|
|
# 格式化日期字段
|
|||
|
|
for d in data:
|
|||
|
|
user_roles = Group.objects.filter(user__id=d["id"]).values_list("name", flat=True)
|
|||
|
|
d["role"] = next(iter(user_roles), "viewer")
|
|||
|
|
if d.get("date_joined"):
|
|||
|
|
try:
|
|||
|
|
d["date_joined"] = d["date_joined"].strftime("%Y-%m-%d %H:%M:%S")
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
else:
|
|||
|
|
d["date_joined"] = ""
|
|||
|
|
if d.get("last_login"):
|
|||
|
|
try:
|
|||
|
|
d["last_login"] = d["last_login"].strftime("%Y-%m-%d %H:%M:%S")
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
else:
|
|||
|
|
d["last_login"] = ""
|
|||
|
|
|
|||
|
|
page_num = int(count / page_size)
|
|||
|
|
if count % page_size > 0:
|
|||
|
|
page_num += 1
|
|||
|
|
pageLabels = buildPageLabels(page=page, page_num=page_num, lang=f_parseRequestLang(request))
|
|||
|
|
pageData = {
|
|||
|
|
"page": page,
|
|||
|
|
"page_size": page_size,
|
|||
|
|
"page_num": page_num,
|
|||
|
|
"count": count,
|
|||
|
|
"pageLabels": pageLabels
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = True
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|||
|
|
else:
|
|||
|
|
msg = __check_msg
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if ret else 0,
|
|||
|
|
"msg": msg,
|
|||
|
|
"data": data,
|
|||
|
|
"pageData": pageData
|
|||
|
|
}
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
def api_openAdd(request):
|
|||
|
|
__ret = False
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
|
|||
|
|
if request.method == 'POST':
|
|||
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|||
|
|
if __check_ret:
|
|||
|
|
params = f_parsePostParams(request)
|
|||
|
|
g_logger.info("UserView.openAdd() params:%s" % str(redact_mapping(params)))
|
|||
|
|
try:
|
|||
|
|
login_user = f_sessionReadUser(request)
|
|||
|
|
if not login_user:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "msg_not_logged_in"))
|
|||
|
|
|
|||
|
|
username = params.get("username", "").strip()
|
|||
|
|
email = params.get("email", "").strip()
|
|||
|
|
password = params.get("password", "").strip()
|
|||
|
|
is_active = params.get("is_active")
|
|||
|
|
is_active = int(is_active)
|
|||
|
|
role = (params.get("role") or "viewer").strip()
|
|||
|
|
if role not in ("system_admin", "algorithm_admin", "operator", "viewer"):
|
|||
|
|
role = "viewer"
|
|||
|
|
|
|||
|
|
if username == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_username_required"))
|
|||
|
|
if email == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_email_required"))
|
|||
|
|
if len(password) < 6 or len(password) > 16:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_password_length"))
|
|||
|
|
|
|||
|
|
if User.objects.filter(username=username).exists():
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_username_exists"))
|
|||
|
|
else:
|
|||
|
|
now = datetime.now()
|
|||
|
|
user = User()
|
|||
|
|
user.username = username
|
|||
|
|
user.set_password(password)
|
|||
|
|
user.email = email
|
|||
|
|
user.date_joined = now
|
|||
|
|
user.is_superuser = 0 # 表单创建均为非超级管理员
|
|||
|
|
user.is_staff = 1
|
|||
|
|
user.is_active = is_active
|
|||
|
|
user.save()
|
|||
|
|
user.groups.set([Group.objects.get(name=role)])
|
|||
|
|
|
|||
|
|
if user.id > 0:
|
|||
|
|
# 添加日志
|
|||
|
|
lang = f_parseRequestLang(request)
|
|||
|
|
LogUtils.add_user_log(login_user.get("id"), username, LogUtils.LOG_TYPE_ADD, lang=lang)
|
|||
|
|
__ret = True
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_add_success")
|
|||
|
|
else:
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_add_failed")
|
|||
|
|
except Exception as e:
|
|||
|
|
__msg = str(e)
|
|||
|
|
else:
|
|||
|
|
__msg = __check_msg
|
|||
|
|
else:
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if __ret else 0,
|
|||
|
|
"msg": __msg
|
|||
|
|
}
|
|||
|
|
g_logger.info("UserView.openAdd() res=%s" % str(res))
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
def api_openEdit(request):
|
|||
|
|
__ret = False
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
|
|||
|
|
if request.method == 'POST':
|
|||
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|||
|
|
if __check_ret:
|
|||
|
|
params = f_parsePostParams(request)
|
|||
|
|
g_logger.info("UserView.openEdit() params:%s" % str(redact_mapping(params)))
|
|||
|
|
try:
|
|||
|
|
login_user = f_sessionReadUser(request)
|
|||
|
|
if not login_user:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "msg_not_logged_in"))
|
|||
|
|
|
|||
|
|
user_id = params.get("id") # 被操作用户id
|
|||
|
|
is_active = params.get("is_active")
|
|||
|
|
username = params.get("username", "").strip()
|
|||
|
|
email = params.get("email", "").strip()
|
|||
|
|
new_password = params.get("new_password", "")
|
|||
|
|
re_password = params.get("re_password", "")
|
|||
|
|
user_id = int(user_id)
|
|||
|
|
is_active = int(is_active)
|
|||
|
|
role = (params.get("role") or "").strip()
|
|||
|
|
|
|||
|
|
if username == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_username_required"))
|
|||
|
|
if email == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_email_required"))
|
|||
|
|
if re_password == "" and new_password == "":
|
|||
|
|
pass
|
|||
|
|
# 未修改密码
|
|||
|
|
else:
|
|||
|
|
# 修改了密码
|
|||
|
|
|
|||
|
|
if new_password == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_new_password_required"))
|
|||
|
|
if re_password == "":
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_confirm_password_required"))
|
|||
|
|
if new_password != re_password:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_password_mismatch"))
|
|||
|
|
if len(new_password) < 6 or len(new_password) > 16:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_new_password_length"))
|
|||
|
|
|
|||
|
|
user = User.objects.filter(id=user_id).first()
|
|||
|
|
if user:
|
|||
|
|
# 验证要修改的用户名是否已经存在start
|
|||
|
|
if user.username == username:
|
|||
|
|
pass
|
|||
|
|
# 用户名未做修改
|
|||
|
|
else:
|
|||
|
|
filter_username = g_database.select(
|
|||
|
|
"select count(1) as count from auth_user where id!=%s and username=%s",
|
|||
|
|
[user_id, username])
|
|||
|
|
filter_username_count = int(filter_username[0]["count"])
|
|||
|
|
if filter_username_count > 0:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_new_username_exists"))
|
|||
|
|
user.username = username # 修改了用户名
|
|||
|
|
# 验证要修改的用户名是否已经存在end
|
|||
|
|
|
|||
|
|
if re_password == "" and new_password == "":
|
|||
|
|
pass
|
|||
|
|
else:
|
|||
|
|
user.set_password(new_password) # 修改了密码
|
|||
|
|
|
|||
|
|
user.email = email
|
|||
|
|
user.is_active = is_active
|
|||
|
|
user.save()
|
|||
|
|
if role in ("system_admin", "algorithm_admin", "operator", "viewer"):
|
|||
|
|
user.groups.set([Group.objects.get(name=role)])
|
|||
|
|
|
|||
|
|
# 添加日志
|
|||
|
|
lang = f_parseRequestLang(request)
|
|||
|
|
LogUtils.add_user_log(login_user.get("id"), username, LogUtils.LOG_TYPE_EDIT, lang=lang)
|
|||
|
|
__ret = True
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_edit_success")
|
|||
|
|
else:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "msg_data_not_exist"))
|
|||
|
|
except Exception as e:
|
|||
|
|
__msg = str(e)
|
|||
|
|
else:
|
|||
|
|
__msg = __check_msg
|
|||
|
|
else:
|
|||
|
|
__msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if __ret else 0,
|
|||
|
|
"msg": __msg
|
|||
|
|
}
|
|||
|
|
g_logger.info("UserView.openEdit() res=%s" % str(res))
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
def api_openDel(request):
|
|||
|
|
ret = False
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
if request.method == 'POST':
|
|||
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|||
|
|
if __check_ret:
|
|||
|
|
params = f_parsePostParams(request)
|
|||
|
|
try:
|
|||
|
|
login_user = f_sessionReadUser(request)
|
|||
|
|
if not login_user:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "msg_not_logged_in"))
|
|||
|
|
|
|||
|
|
user_id = int(params.get("id"))
|
|||
|
|
if not user_id:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_request_params_invalid"))
|
|||
|
|
|
|||
|
|
login_user_id = int(login_user.get("id"))
|
|||
|
|
if login_user_id == user_id:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_super_admin_no_delete_self"))
|
|||
|
|
|
|||
|
|
user = User.objects.filter(id=user_id)
|
|||
|
|
if len(user) > 0:
|
|||
|
|
user = user[0]
|
|||
|
|
if user.is_superuser == 1:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_super_admin_no_delete"))
|
|||
|
|
else:
|
|||
|
|
if user.delete():
|
|||
|
|
ret = True
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_failed_to_delete")
|
|||
|
|
else:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "msg_data_not_exist"))
|
|||
|
|
except Exception as e:
|
|||
|
|
msg = str(e)
|
|||
|
|
else:
|
|||
|
|
msg = __check_msg
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if ret else 0,
|
|||
|
|
"msg": msg
|
|||
|
|
}
|
|||
|
|
g_logger.info("UserView.openDel() res=%s" % str(res))
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
|
|||
|
|
def api_openInfo(request):
|
|||
|
|
"""获取单条用户详情"""
|
|||
|
|
ret = False
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
info = {}
|
|||
|
|
|
|||
|
|
if request.method == "GET":
|
|||
|
|
__check_ret, __check_msg = f_checkRequestSafe(request)
|
|||
|
|
if __check_ret:
|
|||
|
|
params = f_parseGetParams(request)
|
|||
|
|
user_id = params.get("id", "")
|
|||
|
|
|
|||
|
|
if not user_id:
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_id_required")
|
|||
|
|
else:
|
|||
|
|
try:
|
|||
|
|
user_id = int(user_id)
|
|||
|
|
user = User.objects.filter(id=user_id).first()
|
|||
|
|
if user:
|
|||
|
|
info = {
|
|||
|
|
"id": user.id,
|
|||
|
|
"username": user.username,
|
|||
|
|
"email": user.email,
|
|||
|
|
"is_active": user.is_active,
|
|||
|
|
"is_superuser": user.is_superuser,
|
|||
|
|
"is_staff": user.is_staff,
|
|||
|
|
"date_joined": user.date_joined.strftime("%Y-%m-%d %H:%M:%S") if user.date_joined else "",
|
|||
|
|
"last_login": user.last_login.strftime("%Y-%m-%d %H:%M:%S") if user.last_login else ""
|
|||
|
|
}
|
|||
|
|
ret = True
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_success")
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_not_exist")
|
|||
|
|
except Exception as e:
|
|||
|
|
msg = str(e)
|
|||
|
|
else:
|
|||
|
|
msg = __check_msg
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_method_not_supported")
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if ret else 0,
|
|||
|
|
"msg": msg,
|
|||
|
|
"info": info
|
|||
|
|
}
|
|||
|
|
g_logger.info("UserView.openInfo() res=%s" % str(res))
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
|
|||
|
|
def api_openCaptcha(request):
|
|||
|
|
"""生成验证码图片视图"""
|
|||
|
|
# 生成验证码
|
|||
|
|
text,image = generate_secure_captcha()
|
|||
|
|
|
|||
|
|
# 存储到session
|
|||
|
|
cur_timestamp = int(time.time())
|
|||
|
|
request.session[g_session_key_captcha] = {
|
|||
|
|
"captcha_text": text,
|
|||
|
|
"captcha_create_timestamp": cur_timestamp, # 创建秒级时间戳
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 创建内存流输出
|
|||
|
|
stream = BytesIO()
|
|||
|
|
image.save(stream, 'PNG')
|
|||
|
|
return HttpResponse(stream.getvalue(), content_type='image/png')
|
|||
|
|
|
|||
|
|
def login(request):
|
|||
|
|
|
|||
|
|
context = {
|
|||
|
|
"projectVersion": PROJECT_VERSION,
|
|||
|
|
"projectFlag": PROJECT_FLAG
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
if request.method == 'POST':
|
|||
|
|
ret = False
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_unknown_error")
|
|||
|
|
|
|||
|
|
params = f_parsePostParams(request)
|
|||
|
|
username = (params.get("username") or params.get("username_s") or "").strip()
|
|||
|
|
password = (params.get("password") or params.get("password_s") or "").strip()
|
|||
|
|
captcha = params.get("captcha", None)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
if g_config.isEnableLoginCaptcha:
|
|||
|
|
if not captcha:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_captcha_missing"))
|
|||
|
|
# 开启了登录验证码功能
|
|||
|
|
session_captcha = request.session.get(g_session_key_captcha, None)
|
|||
|
|
if not session_captcha:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_captcha_not_found"))
|
|||
|
|
|
|||
|
|
if session_captcha:
|
|||
|
|
captcha_text = session_captcha.get("captcha_text", "")
|
|||
|
|
captcha_create_timestamp = session_captcha.get("captcha_create_timestamp", 0)
|
|||
|
|
cur_timestamp = int(time.time())
|
|||
|
|
|
|||
|
|
# 验证码过期判断
|
|||
|
|
if (cur_timestamp - captcha_create_timestamp) > 300:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_captcha_expired"))
|
|||
|
|
|
|||
|
|
# 验证码相同判断
|
|||
|
|
if captcha_text != captcha:
|
|||
|
|
raise Exception(LANG_VIEWS_T(request, "user_captcha_incorrect"))
|
|||
|
|
if username and password:
|
|||
|
|
user = User.objects.filter(username=username).first()
|
|||
|
|
if user:
|
|||
|
|
if user.is_active:
|
|||
|
|
authenticated_user = authenticate(request, username=username, password=password)
|
|||
|
|
if authenticated_user is not None:
|
|||
|
|
auth_login(request, authenticated_user)
|
|||
|
|
user.first_name = "cec=0"
|
|||
|
|
user.last_login = datetime.now()
|
|||
|
|
user.save()
|
|||
|
|
|
|||
|
|
# 保留兼容旧模板的数据;鉴权和授权以 request.user 为准。
|
|||
|
|
request.session[g_session_key_user] = {
|
|||
|
|
"id": user.id,
|
|||
|
|
"username": username,
|
|||
|
|
"email": user.email,
|
|||
|
|
"is_superuser": user.is_superuser,
|
|||
|
|
"is_active": user.is_active,
|
|||
|
|
"is_staff": user.is_staff,
|
|||
|
|
"log_debug": 1 if g_config.logDebug else 0,
|
|||
|
|
}
|
|||
|
|
request.session.pop(g_session_key_captcha, None)
|
|||
|
|
|
|||
|
|
# 记录登录日志
|
|||
|
|
LogUtils.add_log(
|
|||
|
|
user_id=user.id,
|
|||
|
|
log_type=LogUtils.LOG_TYPE_LOGIN,
|
|||
|
|
content=f"用户登录[{username}]",
|
|||
|
|
state=LogUtils.STATE_SUCCESS
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
ret = True
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_login_success")
|
|||
|
|
else:
|
|||
|
|
continuous_error_count = 0
|
|||
|
|
try:
|
|||
|
|
vals = user.first_name.split(",")
|
|||
|
|
for val in vals:
|
|||
|
|
array = val.split("=")
|
|||
|
|
if len(array) == 2:
|
|||
|
|
if array[0] == "cec":
|
|||
|
|
continuous_error_count = int(array[1])
|
|||
|
|
except:
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
continuous_error_count += 1
|
|||
|
|
if continuous_error_count > 6:
|
|||
|
|
is_active = False
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_password_error_lock") % continuous_error_count
|
|||
|
|
else:
|
|||
|
|
is_active = True
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_password_error_count") % continuous_error_count
|
|||
|
|
user.is_active = is_active
|
|||
|
|
user.first_name = "cec=%d"%continuous_error_count
|
|||
|
|
user.save()
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_account_locked")
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "user_not_registered")
|
|||
|
|
else:
|
|||
|
|
msg = LANG_VIEWS_T(request, "msg_invalid_parameter")
|
|||
|
|
except Exception as e:
|
|||
|
|
msg = str(e)
|
|||
|
|
|
|||
|
|
res = {
|
|||
|
|
"code": 1000 if ret else 0,
|
|||
|
|
"msg": msg
|
|||
|
|
}
|
|||
|
|
return f_responseJson(res)
|
|||
|
|
else:
|
|||
|
|
context["isEnableLoginCaptcha"] = 1 if g_config.isEnableLoginCaptcha else 0
|
|||
|
|
return render(request, 'app/user/login.html', context)
|
|||
|
|
|
|||
|
|
def logout(request):
|
|||
|
|
|
|||
|
|
# 记录退出登录日志
|
|||
|
|
if request.session.has_key(g_session_key_user):
|
|||
|
|
user_info = request.session.get(g_session_key_user)
|
|||
|
|
user_id = user_info.get('id', 0)
|
|||
|
|
username = user_info.get('username', '未知用户')
|
|||
|
|
|
|||
|
|
# 记录日志
|
|||
|
|
if user_id:
|
|||
|
|
LogUtils.add_log(
|
|||
|
|
user_id=user_id,
|
|||
|
|
log_type=LogUtils.LOG_TYPE_LOGOUT,
|
|||
|
|
content=f"用户退出[{username}]",
|
|||
|
|
state=LogUtils.STATE_SUCCESS
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
del request.session[g_session_key_user]
|
|||
|
|
|
|||
|
|
if request.session.has_key(g_session_key_captcha):
|
|||
|
|
del request.session[g_session_key_captcha]
|
|||
|
|
|
|||
|
|
auth_logout(request)
|
|||
|
|
|
|||
|
|
return redirect("/login")
|