diff --git a/accounts/views.py b/accounts/views.py index ebc35ff..a294282 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -89,7 +89,10 @@ def login_submit(request): request.session["user_id"] = user["user_id"] request.session["username"] = user["username"] - request.session["permission"] = user["permission"] + try: + request.session["permission"] = int(user["permission"]) if user.get("permission") is not None else 1 + except Exception: + request.session["permission"] = 1 # Clear challenge to prevent reuse for k in ("challenge_username", "challenge_nonce"): diff --git a/db.sqlite3 b/db.sqlite3 index fb0e914..40cdfd4 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/elastic/es_connect.py b/elastic/es_connect.py index 0197433..c0b1f3d 100644 --- a/elastic/es_connect.py +++ b/elastic/es_connect.py @@ -5,8 +5,6 @@ Django版本的ES连接和操作模块 from elasticsearch import Elasticsearch from elasticsearch_dsl import connections import os -import json -import re from .documents import AchievementDocument, UserDocument, GlobalDocument from .indexes import ACHIEVEMENT_INDEX_NAME, USER_INDEX_NAME, GLOBAL_INDEX_NAME import hashlib @@ -323,45 +321,23 @@ def _compute_hist(range_gte: str, interval: str, fmt: str): buckets = getattr(resp.aggs, 'b').buckets return [{"label": b.key_as_string, "count": b.doc_count} for b in buckets] -def _parse_type_from_data(data_str: str): - try: - obj = json.loads(data_str) - if isinstance(obj, dict): - for k in ("数据类型", "类型", "type"): - if k in obj and obj.get(k): - return str(obj.get(k)).strip().strip(';') - except Exception: - pass - try: - m = re.search(r'"数据类型"\s*:\s*"(.*?)"', data_str) - if m: - return str(m.group(1)).strip().strip(';') - except Exception: - pass - return None - -def _compute_type_counts_dynamic(range_gte: str): - s = AchievementDocument.search() - s = s.filter('range', time={'gte': range_gte, 'lte': 'now'}) - s = s.query('match_all') - counts_map = {} - for hit in s.scan(): - t = _parse_type_from_data(getattr(hit, 'data', '') or '') - if not t: - continue - counts_map[t] = counts_map.get(t, 0) + 1 - try: - ensure_type_in_list(t) - except Exception: - pass - return [{"type": k, "count": int(v)} for k, v in counts_map.items()] +def _compute_type_counts(range_gte: str, types: list): + counts = [] + for t in types: + s = AchievementDocument.search() + s = s.filter('range', time={'gte': range_gte, 'lte': 'now'}) + s = s.query('match_phrase', data=str(t)) + total = s.count() + counts.append({"type": str(t), "count": int(total)}) + return counts def compute_analytics(): + types = get_type_list() days = _compute_hist('now-10d/d', 'day', 'yyyy-MM-dd') weeks = _compute_hist('now-10w/w', 'week', 'yyyy-ww') months = _compute_hist('now-10M/M', 'month', 'yyyy-MM') - pie_1m = _compute_type_counts_dynamic('now-1M/M') - pie_12m = _compute_type_counts_dynamic('now-12M/M') + pie_1m = _compute_type_counts('now-1M/M', types) + pie_12m = _compute_type_counts('now-12M/M', types) return { "last_10_days": days[-10:], "last_10_weeks": weeks[-10:], @@ -406,11 +382,16 @@ def write_user_data(user_data): bool: 写入成功返回True,失败返回False """ try: + # enforce integer permission + try: + perm_val = int(user_data.get('permission', 1)) + except Exception: + perm_val = 1 user = UserDocument( user_id=user_data.get('user_id'), username=user_data.get('username'), password=user_data.get('password'), - permission=user_data.get('permission', 1) + permission=perm_val ) user.save() print(f"用户数据写入成功: {user_data.get('username')}") @@ -460,7 +441,7 @@ def get_user_by_username(username): "user_id": hit.user_id, "username": hit.username, "password": hit.password, - "permission": hit.permission + "permission": int(hit.permission) } return None except Exception as e: @@ -479,7 +460,7 @@ def get_all_users(): users.append({ "user_id": hit.user_id, "username": hit.username, - "permission": hit.permission + "permission": int(hit.permission) }) return users @@ -497,73 +478,22 @@ def get_user_by_id(user_id): return { "user_id": hit.user_id, "username": hit.username, - "permission": hit.permission, + "permission": int(hit.permission), } return None except Exception as e: print(f"获取用户数据失败: {str(e)}") return None -def delete_user_by_username(username): - """ - 根据用户名删除用户 - - 参数: - username (str): 用户名 - - 返回: - bool: 删除成功返回True,失败返回False - """ - try: - search = UserDocument.search() - search = search.query("term", username=username) - response = search.execute() - - if response.hits: - user = response.hits[0] - user.delete() - print(f"用户 {username} 删除成功") - return True - return False - except Exception as e: - print(f"删除用户失败: {str(e)}") - return False - -def update_user_permission(username, new_permission): - """ - 更新用户权限 - - 参数: - username (str): 用户名 - new_permission (int): 新权限级别 - - 返回: - bool: 更新成功返回True,失败返回False - """ - try: - search = UserDocument.search() - search = search.query("term", username=username) - response = search.execute() - - if response.hits: - user = response.hits[0] - user.permission = new_permission - user.save() - print(f"用户 {username} 权限更新为 {new_permission}") - return True - return False - except Exception as e: - print(f"更新用户权限失败: {str(e)}") - return False - def delete_user_by_id(user_id): try: search = UserDocument.search() search = search.query("term", user_id=int(user_id)) response = search.execute() if response.hits: - user = response.hits[0] - user.delete() + hit = response.hits[0] + doc = UserDocument.get(id=hit.meta.id) + doc.delete() return True return False except Exception as e: @@ -576,14 +506,15 @@ def update_user_by_id(user_id, username=None, permission=None, password=None): search = search.query("term", user_id=int(user_id)) response = search.execute() if response.hits: - user = response.hits[0] + hit = response.hits[0] + doc = UserDocument.get(id=hit.meta.id) if username is not None: - user.username = username + doc.username = username if permission is not None: - user.permission = int(permission) + doc.permission = int(permission) if password is not None: - user.password = password - user.save() + doc.password = password + doc.save() return True return False except Exception as e: diff --git a/elastic/templates/elastic/users.html b/elastic/templates/elastic/users.html index 406dc68..b42a75f 100644 --- a/elastic/templates/elastic/users.html +++ b/elastic/templates/elastic/users.html @@ -407,8 +407,8 @@ users.forEach(user => { const row = document.createElement('tr'); - // 根据权限值显示权限名称 - const permissionText = user.permission === 0 ? '管理员' : '普通用户'; + // 根据权限值显示权限名称 + const permissionText = Number(user.permission) === 0 ? '管理员' : '普通用户'; row.innerHTML = ` ${user.user_id} @@ -496,9 +496,9 @@ let response; if (userId) { - // 更新用户 response = await fetch(`/elastic/users/${userId}/update/`, { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken @@ -506,9 +506,9 @@ body: JSON.stringify(data) }); } else { - // 添加用户 response = await fetch('/elastic/users/add/', { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken @@ -540,6 +540,7 @@ const csrftoken = getCookie('csrftoken'); const response = await fetch(`/elastic/users/${userId}/delete/`, { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken diff --git a/elastic/urls.py b/elastic/urls.py index 39ae962..785a437 100644 --- a/elastic/urls.py +++ b/elastic/urls.py @@ -22,10 +22,8 @@ urlpatterns = [ # 用户管理 path('users/', views.get_users, name='get_users'), path('users/add/', views.add_user, name='add_user'), - path('users//delete/', views.delete_user, name='delete_user'), - path('users//update/', views.update_user, name='update_user'), - path('users//delete/', views.delete_user_by_id_view, name='delete_user_by_id'), path('users//update/', views.update_user_by_id_view, name='update_user_by_id'), + path('users//delete/', views.delete_user_by_id_view, name='delete_user_by_id'), # 图片上传与确认 path('upload-page/', views.upload_page, name='upload_page'), diff --git a/elastic/views.py b/elastic/views.py index 19db34c..940d00a 100644 --- a/elastic/views.py +++ b/elastic/views.py @@ -13,7 +13,7 @@ from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie, csrf_protect from .es_connect import * -from openai import OpenAI +from .es_connect import update_user_by_id as es_update_user_by_id, delete_user_by_id as es_delete_user_by_id from PIL import Image @@ -107,7 +107,7 @@ def delete_data(request, doc_id): if not existing: return JsonResponse({"status": "error", "message": "数据不存在"}, status=404) - is_admin = (user_existing.get('permission') ) == 0 + is_admin = int(user_existing.get('permission')) == 0 is_owner = str(existing.get("writer_id", "")) == str(request.session.get("user_id")) if not (is_admin or is_owner): @@ -143,7 +143,7 @@ def update_data(request, doc_id): if not existing: return JsonResponse({"status": "error", "message": "数据不存在"}, status=404) - is_admin = (user_existing.get('permission')) == 0 + is_admin = int(user_existing.get('permission')) == 0 is_owner = str(existing.get("writer_id", "")) == str(request.session.get("user_id")) if not (is_admin or is_owner): @@ -188,7 +188,7 @@ def get_data(request, doc_id): def add_user(request): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: payload = json.loads(request.body.decode("utf-8")) @@ -224,7 +224,7 @@ def add_user(request): def get_users(request): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: q = (request.GET.get("search") or "").strip() @@ -236,41 +236,12 @@ def get_users(request): return JsonResponse({"status": "error", "message": str(e)}, status=500) -@require_http_methods(["DELETE"]) -@csrf_exempt -def delete_user(request, username): - """删除用户""" - try: - success = delete_user_by_username(username) - if success: - return JsonResponse({"status": "success", "message": "用户删除成功"}) - else: - return JsonResponse({"status": "error", "message": "用户删除失败"}, status=500) - except Exception as e: - return JsonResponse({"status": "error", "message": str(e)}, status=500) - - -@require_http_methods(["PUT"]) -@csrf_exempt -def update_user(request, username): - """更新用户权限""" - try: - data = json.loads(request.body.decode('utf-8')) - new_permission = int(data.get('permission', 1)) - success = update_user_permission(username, new_permission) - if success: - return JsonResponse({"status": "success", "message": "用户权限更新成功"}) - else: - return JsonResponse({"status": "error", "message": "用户权限更新失败"}, status=500) - except Exception as e: - return JsonResponse({"status": "error", "message": str(e)}, status=500) - @require_http_methods(["POST"]) @csrf_protect def update_user_by_id_view(request, user_id): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: payload = json.loads(request.body.decode("utf-8")) @@ -285,7 +256,7 @@ def update_user_by_id_view(request, user_id): return JsonResponse({"status": "error", "message": "用户名已存在"}, status=409) if new_password and len(new_password) < 6: return JsonResponse({"status": "error", "message": "密码长度至少为6位"}, status=400) - ok = update_user_by_id( + ok = es_update_user_by_id( user_id, username=new_username if new_username else None, permission=int(new_permission) if new_permission is not None else None, @@ -300,9 +271,9 @@ def update_user_by_id_view(request, user_id): def delete_user_by_id_view(request, user_id): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) - ok = delete_user_by_id(user_id) + ok = es_delete_user_by_id(user_id) if not ok: return JsonResponse({"status": "error", "message": "用户删除失败"}, status=500) return JsonResponse({"status": "success", "message": "用户删除成功"}) @@ -325,6 +296,7 @@ def string_to_json(s): # 移植自 a.py 的核心:调用大模型进行 OCR/信息抽取 def ocr_and_extract_info(image_path: str): + from openai import OpenAI def encode_image(path: str) -> str: with open(path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") @@ -519,7 +491,9 @@ def manage_page(request): from django.shortcuts import redirect return redirect("/accounts/login/") - # is_admin = (request.session.get("permission", 1) == 0) + if int(request.session.get("permission", 1)) != 0: + from django.shortcuts import redirect + return redirect("/main/home/") raw_results = search_all() # if not is_admin: # uid = str(session_user_id) @@ -544,7 +518,7 @@ def user_manage(request): if session_user_id is None: from django.shortcuts import redirect return redirect("/accounts/login/") - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: from django.shortcuts import redirect return redirect("/main/home/") user_id_qs = request.GET.get("user_id") diff --git a/main/views.py b/main/views.py index eaa6fd3..db02461 100644 --- a/main/views.py +++ b/main/views.py @@ -16,10 +16,18 @@ def home(request): perm = request.session.get("permission") if perm is None and uid is not None: u = get_user_by_id(uid) - perm = (u or {}).get("permission", 1) + try: + perm = int((u or {}).get("permission", 1)) + except Exception: + perm = 1 request.session["permission"] = perm + else: + try: + perm = int(perm) + except Exception: + perm = 1 context = { "user_id": uid, - "is_admin": (perm == 0), + "is_admin": (int(perm) == 0), } return render(request, "main/home.html", context) \ No newline at end of file