diff --git a/db.sqlite3 b/db.sqlite3
index d01f075..d2e1512 100644
Binary files a/db.sqlite3 and b/db.sqlite3 differ
diff --git a/elastic/es_connect.py b/elastic/es_connect.py
index 9abac50..cd4e0f7 100644
--- a/elastic/es_connect.py
+++ b/elastic/es_connect.py
@@ -730,7 +730,10 @@ def get_all_users():
users.append({
"user_id": hit.user_id,
"username": hit.username,
- "permission": int(hit.permission)
+ "permission": int(hit.permission),
+ "email": getattr(hit, 'email', None),
+ "key": list(getattr(hit, 'key', []) or []),
+ "manage_key": list(getattr(hit, 'manage_key', []) or []),
})
return users
@@ -749,6 +752,9 @@ def get_user_by_id(user_id):
"user_id": hit.user_id,
"username": hit.username,
"permission": int(hit.permission),
+ "email": getattr(hit, 'email', None),
+ "key": list(getattr(hit, 'key', []) or []),
+ "manage_key": list(getattr(hit, 'manage_key', []) or []),
}
return None
except Exception as e:
diff --git a/elastic/indexes.py b/elastic/indexes.py
index ce9f83a..d03006e 100644
--- a/elastic/indexes.py
+++ b/elastic/indexes.py
@@ -1,5 +1,5 @@
-INDEX_NAME = "wordsearch2666661"
-USER_NAME = "users11111666789"
+INDEX_NAME = "wordsearch21"
+USER_NAME = "users16"
ACHIEVEMENT_INDEX_NAME = INDEX_NAME
USER_INDEX_NAME = USER_NAME
-GLOBAL_INDEX_NAME = "global11111111"
+GLOBAL_INDEX_NAME = "global11121"
diff --git a/elastic/templates/elastic/users.html b/elastic/templates/elastic/users.html
index fb3e7fd..9e8bf48 100644
--- a/elastic/templates/elastic/users.html
+++ b/elastic/templates/elastic/users.html
@@ -216,20 +216,49 @@
-
+ {% if is_student %}
+
+ {% else %}
+ {% if is_tutor %}
+
+ {% endif %}
-
- 操作成功!
-
-
- 操作失败!
-
+
操作成功!
+
操作失败!
@@ -247,12 +276,11 @@
操作 |
-
-
-
+
+ {% endif %}
@@ -511,7 +539,10 @@
}
// 事件监听器
- document.getElementById('addUserBtn').addEventListener('click', openAddModal);
+ const addBtn = document.getElementById('addUserBtn');
+ if (addBtn) {
+ addBtn.addEventListener('click', openAddModal);
+ }
document.getElementById('userForm').addEventListener('submit', saveUser);
@@ -523,15 +554,21 @@
});
});
- document.getElementById('searchBtn').addEventListener('click', function() {
- const searchTerm = document.getElementById('searchInput').value;
- loadUsers(searchTerm);
- });
+ const searchBtn = document.getElementById('searchBtn');
+ if (searchBtn) {
+ searchBtn.addEventListener('click', function() {
+ const searchTerm = document.getElementById('searchInput').value;
+ loadUsers(searchTerm);
+ });
+ }
- document.getElementById('resetBtn').addEventListener('click', function() {
- document.getElementById('searchInput').value = '';
- loadUsers();
- });
+ const resetBtn = document.getElementById('resetBtn');
+ if (resetBtn) {
+ resetBtn.addEventListener('click', function() {
+ document.getElementById('searchInput').value = '';
+ loadUsers();
+ });
+ }
// 点击模态框外部关闭模态框
window.addEventListener('click', function(event) {
@@ -572,7 +609,34 @@
// 页面加载时获取用户列表
document.addEventListener('DOMContentLoaded', function() {
- loadUsers();
+ const selfForm = document.getElementById('selfPwdForm');
+ if (selfForm) {
+ selfForm.addEventListener('submit', async (e) => {
+ e.preventDefault();
+ const uid = document.getElementById('selfUserId').value;
+ const pwd = document.getElementById('password').value;
+ const cpwd = document.getElementById('confirmPassword').value;
+ if (pwd !== cpwd) { showNotification('密码和确认密码不匹配', false); return; }
+ if ((pwd || '').length < 6) { showNotification('密码长度至少为6位', false); return; }
+ try {
+ const csrftoken = getCookie('csrftoken');
+ const resp = await fetch(`/elastic/users/${uid}/update/`, {
+ method: 'POST', credentials: 'same-origin',
+ headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken || '' },
+ body: JSON.stringify({ password: pwd })
+ });
+ const result = await resp.json();
+ if (resp.ok && result.status === 'success') { showNotification('修改成功'); }
+ else { showNotification(result.message || '操作失败', false); }
+ } catch (error) {
+ showNotification('保存失败', false);
+ }
+ });
+ }
+ const tbody = document.getElementById('usersTableBody');
+ if (tbody) {
+ loadUsers();
+ }
});
// 为表格中的编辑和删除按钮添加事件监听器
diff --git a/elastic/views.py b/elastic/views.py
index b79f6cd..cfb06af 100644
--- a/elastic/views.py
+++ b/elastic/views.py
@@ -222,16 +222,27 @@ def add_user(request):
@require_http_methods(["GET"])
def get_users(request):
- if request.session.get("user_id") is None:
+ uid = request.session.get("user_id")
+ if uid is None:
return JsonResponse({"status": "error", "message": "未登录"}, status=401)
- if int(request.session.get("permission", 1)) != 0:
- return JsonResponse({"status": "error", "message": "无权限"}, status=403)
try:
+ is_admin = int(request.session.get("permission", 1)) == 0
+ requester = get_user_by_id(uid) or {}
+ mgr_keys = set(requester.get("manage_key") or [])
q = (request.GET.get("search") or "").strip()
users = get_all_users()
+ if is_admin:
+ filtered = users
+ elif mgr_keys:
+ def match_manage(user):
+ ukeys = set(user.get("key") or [])
+ return bool(ukeys & mgr_keys)
+ filtered = [u for u in users if match_manage(u)]
+ else:
+ filtered = [u for u in users if str(u.get("user_id")) == str(uid)]
if q:
- users = [u for u in users if q in str(u.get("username", ""))]
- return JsonResponse({"status": "success", "data": users})
+ filtered = [u for u in filtered if q in str(u.get("username", ""))]
+ return JsonResponse({"status": "success", "data": filtered})
except Exception as e:
return JsonResponse({"status": "error", "message": str(e)}, status=500)
@@ -239,10 +250,9 @@ def get_users(request):
@require_http_methods(["POST"])
@csrf_protect
def update_user_by_id_view(request, user_id):
- if request.session.get("user_id") is None:
+ uid = request.session.get("user_id")
+ if uid is None:
return JsonResponse({"status": "error", "message": "未登录"}, status=401)
- if int(request.session.get("permission", 1)) != 0:
- return JsonResponse({"status": "error", "message": "无权限"}, status=403)
try:
payload = json.loads(request.body.decode("utf-8"))
except Exception:
@@ -250,21 +260,41 @@ def update_user_by_id_view(request, user_id):
new_username = (payload.get("username") or "").strip()
new_permission = payload.get("permission")
new_password = (payload.get("password") or "").strip()
- if new_username:
- other = get_user_by_username(new_username)
- if other and int(other.get("user_id", -1)) != int(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 = 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,
- password=new_password if new_password else None,
- )
- if not ok:
- return JsonResponse({"status": "error", "message": "用户更新失败"}, status=500)
- return JsonResponse({"status": "success", "message": "用户更新成功"})
+
+ is_admin = int(request.session.get("permission", 1)) == 0
+ requester = get_user_by_id(uid) or {}
+ target = get_user_by_id(user_id) or {}
+ requester_mgr = set(requester.get("manage_key") or [])
+ target_keys = set(target.get("key") or [])
+
+ if is_admin:
+ if new_username:
+ other = get_user_by_username(new_username)
+ if other and int(other.get("user_id", -1)) != int(user_id):
+ return JsonResponse({"status": "error", "message": "用户名已存在"}, status=409)
+ 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,
+ password=new_password if new_password else None,
+ )
+ return JsonResponse({"status": "success"}) if ok else JsonResponse({"status": "error", "message": "用户更新失败"}, status=500)
+
+ if str(uid) == str(user_id):
+ if not new_password:
+ return JsonResponse({"status": "error", "message": "仅允许修改密码"}, status=400)
+ ok = es_update_user_by_id(user_id, password=new_password)
+ return JsonResponse({"status": "success"}) if ok else JsonResponse({"status": "error", "message": "用户更新失败"}, status=500)
+
+ if requester_mgr and (target_keys & requester_mgr):
+ if not new_password or new_username or new_permission is not None:
+ return JsonResponse({"status": "error", "message": "导师仅允许修改密码"}, status=403)
+ ok = es_update_user_by_id(user_id, password=new_password)
+ return JsonResponse({"status": "success"}) if ok else JsonResponse({"status": "error", "message": "用户更新失败"}, status=500)
+
+ return JsonResponse({"status": "error", "message": "无权限"}, status=403)
@require_http_methods(["POST"])
@csrf_protect
@@ -598,11 +628,16 @@ def user_manage(request):
if session_user_id is None:
from django.shortcuts import redirect
return redirect("/accounts/login/")
- if int(request.session.get("permission", 1)) != 0:
- from django.shortcuts import redirect
- return redirect("/main/home/")
+ is_admin = int(request.session.get("permission", 1)) == 0
+ me = get_user_by_id(session_user_id) or {}
+ has_manage = bool(me.get("manage_key"))
user_id_qs = request.GET.get("user_id")
- context = {"user_id": user_id_qs or session_user_id}
+ context = {
+ "user_id": user_id_qs or session_user_id,
+ "is_admin": is_admin,
+ "is_tutor": (not is_admin) and has_manage,
+ "is_student": (not is_admin) and (not has_manage),
+ }
return render(request, "elastic/users.html", context)
@require_http_methods(["GET"])
diff --git a/main/templates/main/home.html b/main/templates/main/home.html
index b0d5afb..61348f7 100644
--- a/main/templates/main/home.html
+++ b/main/templates/main/home.html
@@ -42,8 +42,8 @@
主页
图片上传与识别
数据管理
- {% if is_admin %}
用户管理
+ {% if is_admin %}
注册码管理
{% endif %}
退出登录