From a484d038941813c1bc28913ac122d5ee66eb72b2 Mon Sep 17 00:00:00 2001 From: Macbook Date: Mon, 15 Dec 2025 10:54:11 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B0=D0=BA=D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=20=D0=BA=D0=BB=D0=B8=D0=B5=D1=82=D0=B0=20=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=D0=B3=D0=BE=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8=D0=BB?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/routers/__pycache__/user.cpython-313.pyc | Bin 5236 -> 6702 bytes api/routers/user.py | 23 +- api/static/js/api.js | 2 +- api/static/js/cookies.js | 4 + api/static/js/index.js | 14 + api/static/js/user.js | 265 ++++++++++++++++--- api/templates/index.html | 2 +- db/handlers/__pycache__/user.cpython-313.pyc | Bin 17124 -> 19225 bytes db/handlers/user.py | 32 ++- 9 files changed, 298 insertions(+), 44 deletions(-) diff --git a/api/routers/__pycache__/user.cpython-313.pyc b/api/routers/__pycache__/user.cpython-313.pyc index 51ca486b99748cbdc8144d6e93a280b8abe9f535..bc1d4359dc29e04f7ff6091ddc6211b608750e2b 100644 GIT binary patch delta 2408 zcmb_dT})I*6rQ-Yx2vY0xY=D`{aN(xuBm+} zl>TUZQ9EhslO^ekeQ8ibOKYk@?MsuIS=VHBLz*^eleS3{h@`1aAA064h^3nJp*NXx z&di*dGxMGK&Ykyu+GKrfu^172uT5@=W~7T&C;s(fU3{cZs6>7F&6rOi)P$A%K5LVp z7|YNRas)T$hLKv(XYQ$3=scqoonlhVZNdw7u`Js~`qwVGJr%1`@S<&~j9-4~d7&Lj z$&1#&1)R%5+jwXi!}YG*1xuIB+Xu^hF8Ue1NB4-;&UCWm-CL`+UtUei! zs5`^SPFgQ)Un~1`Suq+*WW~WqLd}O*SrUy646Auy`UJHAlv)HLE`X3_`h~D@qy$W! z=J;L^zo1d{qoweIJ0n%3q>Aynw6roKHKe45E3c=e*0iNK50Rgq}hM<2q<>Lwh_$6CySCKE;mak18J);*TJ^sD1fVxV%c~Aq2NY@dI=0_Uyqeu)!B>zL9y~P1PC29meP4r zTl&nxatOEJk9rDWfxWIEApSEh4`4vu)6h;s+teZsU|%8qP3LXY;LqwqY9yG5WQF0Q zkirvTu#@euE4$3Dvai@pc8%R&lVDA;Nm?n^VwtYfckRwsZQ!I9bHP)Z6@%fhmS@$@ zyCf2hCe$iET?WFZ*D{_psFC=I;TXIWH=kO;MG?KJFL67-%$kk|W5K~lKYvQTJmM2`jk|EWhgDRq%Eyf$*Zf7k=Zu7=XVdXI%dp8=ey2zv9bW$ z*T(_}ne)&Cb3c7IZ(?^1a&*iYkz+faGjsVQ-U3m^wia$H!?%m@HXFHJ?9YeJ9XH`@AU_^8h$AjozHk+=vW20cU~DiF-W@p=Io26W1l4lx zz+q5Jx$uAh3TSpEACS4wu&U-(4G5oM3CtYSdOlUl1%EovKx@(E*t7tq#axaZbhWuu z*8qME*LOjMEA`=SA67ZHK&=H8=g(YL9rUu*spAybO>bBm!f)u;goYxaqe&h^V+DTz zlfaHI*@Vm{*tOIcy9wPX_BoqKy$5>g`HUeDAXkLonLg#z|5}ECX+nV4A?HX;2nb#{ zGXH|WB84crwVYc-(Q^$?zqkVUnd`>|52{8Tq6ZCNjSzX=s+L4vB9eX(|MBWFy9Ern zk)kc4G$Jo$ck#_@^w5aHE1<@V99v8p%KlIydMe@*m#U%a1HU*gGqMcX0iCsJuKmGe zVkihEcMJqCm9rxxUsp9F*)H^D>@_KS&GXw zw6y80e#T%uZ#rjUj{WSwA-2Dt*$zK21ZPSrGbIi8OB$}6N|$WNNE^=TzcWb>ZSG59 zR$Rr*Ro{a-$ck&3xppoe6}9{^Ys9*$hlS2db*!NBzM=B3czXvNWDIXb_#MB?-;Aa` z*uS1k%T{hT@bT$2BDWhgdp+iMv)G>Wy5u>6?*~jGNp2=shmbyVpP8L6Z9A)$|cdT z>G*Isc`UM7-3eoy4)IPJEpAmFdDl#s(%wyTNW{Kz+dNl~MI@ZWvjUj2W+WKSxZZM| zRajZ~sEgq}k5)BKw5L~XnM0-6Hr_eU6<@IzR)9I%N`ERI@-fd2?!EI-Q~Oj`x@pH8 bGUBQ$ug-JDy?22(n6qWH)3%!IfCK#v+Jq^4 delta 1251 zcmZ`&&1)M+6rb50YgZp$Sq4O5klu0&kK6;LrMZ-X{{yGTVtUPf$%eM7onou;X&!0o z+)1sD)HP?g#BPh*{Iyqxyds<9=vYqr|Dr&X-{2Fl&(DuVF?0WkX?OFr0_3#)>GtuM z8g9PEd6Yt!Viop?b=gJz7JtGQpD>vr6;1{n(Hyr?pp<fIDfTMUzF5}hxMMUwW6V9zSOv~yC*iBu2L|R`VJjMZ9;;|h0t!YW zpFE8L%WRofnUhi;O{Pq;WwDH8!2{!3@t9GWt*APn7h6ifmY(Gn{B7jZ-3*;%>%Q!&+p%#-_GBBm* zZw>kwp+u@Nf|I0(p<;U@@ME~Cs3A|#d2-Y3yIpUME|q8TB#qNw!UjXs)&;Sbc$efR zZ`H-#rFoQ}Hh61BJZ&~m{;AFhXAr+BCH0*mdLMiANPFGwcfHQX-k07+%MDyPP6m{) z%oCImYFZ>u(g8JPM9maQRnnV^rcm_yw+8YJIwlh2n*>zJ$ew~)wIN00%O}8hR(V3P zbmApTZoBRI{@Mn;N4|p|=XQU$8rrNJLAk~yl^K`!aPg5sR*6U+b+?0cuOIZ%=kL|R+t?<)HqKb=}f!B4@f*P g;ZkudU*PuR)^mmn>29J9#e*5xEUtr5ni3TGA9rl~AOHXW diff --git a/api/routers/user.py b/api/routers/user.py index 36025bc..2349729 100644 --- a/api/routers/user.py +++ b/api/routers/user.py @@ -8,8 +8,10 @@ router = APIRouter() @router.get("/", name="userInfo", summary="Получение информации о пользователе") -async def get_user(): - return +async def get_user(request_data: dict = Depends(requestDict)): + userId = int(request_data.get("query").get("userId")) + logger.info(f"Получение информации о пользователе {userId}") + return await UserHandler.get(userId) @router.post("/", summary="Правка данных пользователя") @@ -17,13 +19,14 @@ async def manage_user(request_data: dict = Depends(requestDict)): response = {"status": "error"} userData = request_data.get("body").get("userData", {}) action = request_data.get("body").get("action") - userId = request_data.get("body").get("userId") + userId = int(request_data.get("body").get("userId")) match action: case "create": result = await UserHandler.add(userData, userId) if result: response["status"] = "ok" case "update": + logger.info(f"Обновление данных пользователя {userId}") result = await UserHandler.edit(userData, user_id=userId) if "error" not in result: response["status"] = "ok" @@ -75,6 +78,20 @@ async def authenticationPage(request: Request): return await render(request) +@router.post("/check", summary="Проверка авторизации") +async def check_authentication(request_data: dict = Depends(requestDict)): + try: + userId = int(request_data.get("body").get("userId")) + logger.info(f"Проверка авторизации пользователя {userId}") + result = await UserHandler.checkActive(userId) + if result: + return {"status": "ok"} + else: + return {"status": "error"} + except: + return {"status": "error"} + + @router.post("/login") async def authentication( request_data: dict = Depends(requestDict), diff --git a/api/static/js/api.js b/api/static/js/api.js index c2783f7..f5148cd 100644 --- a/api/static/js/api.js +++ b/api/static/js/api.js @@ -19,7 +19,7 @@ function hideLoader() { } export async function apiRequest(url, payload = {}, method = 'POST') { - method = method.toUpperCase(); + method = typeof method === 'string' ? method.toUpperCase() : 'POST'; let finalUrl = url; let options = { diff --git a/api/static/js/cookies.js b/api/static/js/cookies.js index f5e774b..3407915 100644 --- a/api/static/js/cookies.js +++ b/api/static/js/cookies.js @@ -26,6 +26,9 @@ export async function setCookie(name, value, days = 180) { const expires = new Date(Date.now() + days * 864e5).toUTCString(); const encodedName = encodeURIComponent(name); + document.cookie = `${encodedName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`; + document.cookie = `${encodedName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; Secure;`; + // ---------- 1. Пытаемся установить безопасную куку ---------- let secureCookie = `${encodedName}=${cookieValue}; expires=${expires}; path=/; Secure; SameSite=Lax`; document.cookie = secureCookie; @@ -45,6 +48,7 @@ export async function setCookie(name, value, days = 180) { return false; // безопасную куку установить не удалось } + export async function getCookie(name) { const cookies = document.cookie ? document.cookie.split('; ') : []; diff --git a/api/static/js/index.js b/api/static/js/index.js index 3df0e8d..0ad78c1 100644 --- a/api/static/js/index.js +++ b/api/static/js/index.js @@ -67,6 +67,19 @@ const predefinedSpecs = { async function getCookieData() { accessData = await getCookie('toolbox_access'); userData = await getCookie('toolbox_user'); + await checkActiveUser(); +} + +async function checkActiveUser() { + const activeCookie = loadFromStorage('active'); + if (!activeCookie || !activeCookie.active || !activeCookie.datetime || Date.now() - activeCookie.datetime > 12 * 60 * 60 * 1000) { + const checkActive = await apiRequest('/user/check', { userId: userData.id }); + if (checkActive.status === 'ok') { + saveToStorage('active', { active: true, datetime: Date.now() }); + } else { + window.clientManager?.initLogout(); + } + } } async function openTab(event, tabId) { @@ -7209,6 +7222,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (!accessData || !userData) { console.warn('Access data or user data not found'); + console.log(accessData, userData); return; } diff --git a/api/static/js/user.js b/api/static/js/user.js index 44a5832..f8cb1c7 100644 --- a/api/static/js/user.js +++ b/api/static/js/user.js @@ -1,4 +1,5 @@ -import { getCookie, deleteCookie } from '/static/js/cookies.js'; +import { apiRequest } from './api.js'; +import { getCookie, deleteCookie, setCookie } from './cookies.js'; class ClientManager { constructor() { @@ -13,11 +14,9 @@ class ClientManager { this.userData = await getCookie('toolbox_user'); this.accessData = await getCookie('toolbox_access'); - if (!this.userData || !this.accessData) { console.warn('User data or access data not found in cookie'); - this.clearUserCookie(); - window.location.href = '/user/login'; + this.initLogout(); } // Вставляем данные пользователя в DOM @@ -35,8 +34,7 @@ class ClientManager { renderUserInfo() { if (!this.userData) { - // Если нет данных, показываем заглушку - this.renderFallbackUser(); + this.initLogout(); return; } @@ -64,37 +62,6 @@ class ClientManager { } - renderFallbackUser() { - const userCard = document.querySelector('.client-card'); - if (userCard) { - userCard.innerHTML = ` -
-
- Гость - -
-
-
Гость
-
- - - Не авторизован - -
-
- -
- `; - } - } - initLogoutHandler() { const logoutBtn = document.getElementById('clientLogoutBtn'); if (logoutBtn) { @@ -105,12 +72,18 @@ class ClientManager { } } + initLogout() { + const logoutBtn = document.getElementById('clientLogoutBtn'); + if (logoutBtn) { + this.handleLogout(logoutBtn); + } + } + handleLogout(button) { // Анимация нажатия button.style.transform = 'scale(0.95)'; // Добавляем иконку загрузки - const originalContent = button.innerHTML; button.innerHTML = ` Выход... @@ -162,6 +135,220 @@ class ClientManager { }; } } + + userProfile() { + const avatarBtn = document.getElementById('userProfile'); + + async function openEditUserModal(user = null) { + const isNew = !user; + const modalId = `profile-edit-user-modal`; + + // Удаляем старую модалку, если есть + const existingModal = document.getElementById(modalId); + if (existingModal) { + existingModal.remove(); + } + + const modalHTML = ` + + `; + + document.body.insertAdjacentHTML('beforeend', modalHTML); + const modal = new bootstrap.Modal(document.getElementById(modalId)); + let photoFile = null; + let removePhoto = false; + + // Обработчики для фото + const changePhotoBtn = document.getElementById(`${modalId}-change-photo-btn`); + const photoInput = document.getElementById(`${modalId}-photo-input`); + const photoPreview = document.getElementById(`${modalId}-photo-preview`); + + changePhotoBtn.addEventListener('click', () => { + photoInput.click(); + }); + + photoInput.addEventListener('change', (e) => { + const file = e.target.files[0]; + if (file) { + if (file.type.startsWith('image/')) { + photoFile = file; + const reader = new FileReader(); + reader.onload = (e) => { + photoPreview.src = e.target.result; + }; + reader.readAsDataURL(file); + removePhoto = false; + } else { + showConfirmationModal('Ошибка', 'Пожалуйста, выберите файл изображения', () => { }); + photoInput.value = ''; + } + } + }); + + if (document.getElementById(`${modalId}-remove-photo-btn`)) { + document.getElementById(`${modalId}-remove-photo-btn`).addEventListener('click', () => { + photoPreview.src = 'static/images/users/default.png'; + photoFile = null; + removePhoto = true; + }); + } + + // Обработчик сохранения + document.getElementById(`${modalId}-save-btn`).addEventListener('click', async () => { + const form = document.getElementById(`${modalId}-form`); + if (!form.checkValidity()) { + form.reportValidity(); + return; + } + + const formUserData = { + login: document.getElementById(`${modalId}-login`).value.trim(), + username: document.getElementById(`${modalId}-username`).value.trim(), + }; + + // Добавляем пароль, если он указан + const password = document.getElementById(`${modalId}-password`).value; + if (password || isNew) { + formUserData.password = password || ''; + } + + // Определяем действие + let action = isNew ? 'create' : 'update'; + + // Обработка фото + if (photoFile) { + if (photoFile.size > 5 * 1024 * 1024) { + showInfo('Фото больше 5 МБ, оно не подходит', 'warning'); + return; + } + formUserData.photo = await new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => resolve(reader.result); + reader.onerror = () => reject(new Error('Ошибка чтения файла')); + + reader.readAsDataURL(photoFile); + }); + + } else if (removePhoto) { + formUserData.photo = ''; + } + + let changedUserData = {}; + if (isNew) { + changedUserData = formUserData; + } else { + changedUserData = Object.keys(formUserData).reduce((acc, key) => { + if (formUserData[key] !== user[key]) { + acc[key] = formUserData[key]; + } + return acc; + }, {}); + } + + if (Object.keys(changedUserData).length === 0) { + showInfo('Нет изменений', 'info'); + return; + } + + // Обновляем данные + if (!isNew) { + changedUserData.id = user.id; + } + + const result = await apiRequest('/user/', { action, userData: changedUserData, userId: user.id }); + + if (result && result.status === 'ok') { + const newUserData = await apiRequest('/user/', { userId: user.id }, 'get'); + await setCookie('toolbox_user', JSON.stringify(newUserData)); + const checkData = await getCookie('toolbox_user'); + if (window.clientManager) { + window.clientManager.userData = newUserData; + window.clientManager.renderUserInfo(); + } + if (modal) { modal.hide(); } + } else { + const errorMessageDiv = document.getElementById(`${modalId}-error-message`); + errorMessageDiv.textContent = result.message; + errorMessageDiv.hidden = false; + } + }); + + modal.show(); + + // Удаляем модалку после скрытия + modal._element.addEventListener('hidden.bs.modal', () => { + modal._element.remove(); + }); + } + + avatarBtn.addEventListener('click', async () => { + await openEditUserModal(this.userData); + }); + } } // Инициализация при загрузке документа @@ -174,6 +361,8 @@ document.addEventListener('DOMContentLoaded', () => { elements.forEach((el, index) => { el.style.animationDelay = `${index * 0.1}s`; }); + + window.clientManager.userProfile(); }); // Экспорт для использования в других модулях diff --git a/api/templates/index.html b/api/templates/index.html index 3979a06..71daa20 100644 --- a/api/templates/index.html +++ b/api/templates/index.html @@ -32,7 +32,7 @@
-
+
Загрузка... diff --git a/db/handlers/__pycache__/user.cpython-313.pyc b/db/handlers/__pycache__/user.cpython-313.pyc index 3287e26494f3facedf93af59553bd95d3a2fde61..d74595cfdbd43748446b3ec63391254335e853f1 100644 GIT binary patch delta 2648 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 SGuYvt6v6$7a5TfLhd%+_&{9YM diff --git a/db/handlers/user.py b/db/handlers/user.py index 88b2855..c13d980 100644 --- a/db/handlers/user.py +++ b/db/handlers/user.py @@ -109,6 +109,20 @@ class UserHandler: else: userData["photo"] = "static/images/users/default.png" deleteImage(user.photo) + if "login" in userData: + uniqueLogin = await CRUD.read( + select(User).where(User.login == userData["login"]) + ) + if uniqueLogin and uniqueLogin.id != user.id: + logger.error("Пользователь с таким логином уже существует") + return {"error": "Пользователь с таким логином уже существует"} + if "username" in userData: + uniqueUserName = await CRUD.read( + select(User).where(User.username == userData["username"]) + ) + if uniqueUserName and uniqueUserName.id != user.id: + logger.error("Пользователь с таким именем уже существует") + return {"error": "Пользователь с таким именем уже существует"} try: userData.pop("id") editedUser = await user.edit(**userData) @@ -156,7 +170,9 @@ class UserHandler: if not user: logger.error("Пользователь с таким id не найден") return {} - return user.toDict() + userdata = user.toDict() + userdata.pop("hashed_password") + return userdata async def delete(id: int, user_id: int = None) -> dict: userRecordsCount = await StocksRecordsHandler.getUserRecords(id) @@ -202,12 +218,26 @@ class UserHandler: ) return True + async def checkActive(id: int) -> bool: + query = select(User).where(User.id == id) + user = await CRUD.read(query) + if not user: + logger.error("Пользователь с таким id не найден") + return False + return user.is_active + async def auth(login: str, password: str) -> dict: query = select(User).where(User.login == login) user = await CRUD.read(query) if not user: logger.error(f"Пользователь с логином {login} не найден") return {} + if not user.is_active: + logger.error(f"Пользователь {user.username} не активен") + await ServiceRecordsHandler.add( + user.id, {"Пользователь не активен": user.username} + ) + return {} if not pwd_verify(password, user.hashed_password): logger.error(f"Неверный пароль пользователя {user.username}") await ServiceRecordsHandler.add(