From 5dbdd43785f95cbe18f723a7acbfbdfb3b71961d Mon Sep 17 00:00:00 2001 From: Kobe Date: Thu, 29 May 2025 15:19:42 +0200 Subject: [PATCH] utils and event logging --- __pycache__/models.cpython-313.pyc | Bin 20607 -> 20607 bytes __pycache__/utils.cpython-313.pyc | Bin 2919 -> 2919 bytes routes/__pycache__/auth.cpython-313.pyc | Bin 6359 -> 6359 bytes routes/__pycache__/contacts.cpython-313.pyc | Bin 15720 -> 15720 bytes .../__pycache__/conversations.cpython-313.pyc | Bin 20141 -> 20141 bytes routes/__pycache__/main.cpython-313.pyc | Bin 35731 -> 39170 bytes .../__pycache__/room_members.cpython-313.pyc | Bin 6798 -> 6798 bytes routes/__pycache__/rooms.cpython-313.pyc | Bin 15036 -> 15036 bytes routes/__pycache__/trash.cpython-313.pyc | Bin 7171 -> 7171 bytes routes/main.py | 83 ++++++++- static/js/events.js | 95 ++++++++++ templates/settings/settings.html | 11 ++ templates/settings/tabs/events.html | 165 ++++++++++++++++++ utils/__init__.py | 21 +++ utils/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 696 bytes .../__pycache__/event_logger.cpython-313.pyc | Bin 0 -> 4462 bytes utils/__pycache__/path_utils.cpython-313.pyc | Bin 0 -> 2189 bytes utils/__pycache__/permissions.cpython-313.pyc | Bin 0 -> 2668 bytes utils/__pycache__/time_utils.cpython-313.pyc | Bin 0 -> 4083 bytes utils/event_logger.py | 132 ++++---------- utils/path_utils.py | 59 +++++++ utils/permissions.py | 83 +++++++++ utils/time_utils.py | 109 ++++++++++++ 23 files changed, 657 insertions(+), 101 deletions(-) create mode 100644 static/js/events.js create mode 100644 templates/settings/tabs/events.html create mode 100644 utils/__init__.py create mode 100644 utils/__pycache__/__init__.cpython-313.pyc create mode 100644 utils/__pycache__/event_logger.cpython-313.pyc create mode 100644 utils/__pycache__/path_utils.cpython-313.pyc create mode 100644 utils/__pycache__/permissions.cpython-313.pyc create mode 100644 utils/__pycache__/time_utils.cpython-313.pyc create mode 100644 utils/path_utils.py create mode 100644 utils/permissions.py create mode 100644 utils/time_utils.py diff --git a/__pycache__/models.cpython-313.pyc b/__pycache__/models.cpython-313.pyc index 19e3c6de6ae7a5981dfccd6cd4a48ac33ee60c4e..15107a8213b6886f7dfdbddf59edb31ee9859124 100644 GIT binary patch delta 21 acmeyrfbstVMy}7iyj%<*5WbPCGyniolLk2e delta 21 bcmeyrfbstVMy}7iyj%=GVD7$=t26)rRE-8; diff --git a/__pycache__/utils.cpython-313.pyc b/__pycache__/utils.cpython-313.pyc index e3bb6dbbadfe4a87fa4b07ee9f2fc3ead441087d..0c3fa99a201c53db0d4cdd4161ae658642ff0f7b 100644 GIT binary patch delta 20 ZcmaDZ_FRnnGcPX}0|VS#0D!BLM(H1O>zZ delta 20 acmca^c-@fuGcPX}0}$NUX}Xd7j06Bjf(DrY diff --git a/routes/__pycache__/contacts.cpython-313.pyc b/routes/__pycache__/contacts.cpython-313.pyc index 82385d22b818d7a3aec78aed2f3811665e982de9..0ce2c564589848c3c6db5da410479ad18476d02e 100644 GIT binary patch delta 23 dcmaD+^`eUJGcPX}0}y--v&cBCy^$}<765A22pIqX delta 23 dcmaD+^`eUJGcPX}0}y=JX_~Q9Ya?HjEdXuC2x$NS diff --git a/routes/__pycache__/conversations.cpython-313.pyc b/routes/__pycache__/conversations.cpython-313.pyc index bc544d10d6f37abf868f34a0587c4651e66912b6..7ea0e732f967cf2621a8709e3d3bf65000dada7c 100644 GIT binary patch delta 25 ecmZ2GmvQY}M!wIyyj%<*5N?rSZ?lnaz8?Ty$_Cm1 delta 25 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 delta 2780 zcma);4QyLi6@c&c?{n-pPV?vH&#!GZ*ZJw%G(W9?D9c*NY?_}YX&cDuzSu90muJ89 zJbO#h(lnEhCeVQHZX|=PY-~epLfVfv0YV@lHdG0yG6k6QLX}o%K*t2D21vjdob#Nm z-H*^L>wD*(d+xpGo^#K;@1EyvV%g?@tF*L);qS`__f1bH&-sIV=v+9wD6lldzGx|wM*ZNAmO)uG0D)*Zlw19d*p_GoR9LbzRtc3jhbvYUt%hn# z=Z@7xgAj~vg{{$AsEyV^ou!vz_0f8$k2XNV=GdA>XvD$JSO`MaQwDjW@o=9wSzBqF zXcVh6m97yFYCc`mgv3%srO@jn-z|KkWWQZz*cYX~hKZXyIc<UBk=Co&B zgRW=d=_K@1pEp0N=}J;f#wX{Yi>CPmshw#ftLIF+re2! z@u{??8qiJ#Tc&i#D7hT&;9VQoPaTfDA&jmaI|ga4A;K`JeY%!Zja)njiZKm`Nk1Zf z*wySBC2>q#?K;MrL|^wVzN2um`+POOPXq=&&+jj21B1MZas&_1JT~1h9kWVq8j@ml zu+l|Ig1C5nu&#EV#QO=w6q9rZVY>(o)izh4XgUn#F4dGMG+70M_jT%DCae%1B78$6 zhQ{h>m+&OQ^w75B)|%fW<-=la=q7abpF_>uS7;h;vwK@fzj;C@Mw{ynVzn5Qh2jYf zt%f?+%DPsiE(nXqM&|-8WPjtJ$XFMTi4$XuJS-N+M(SVqfB`m5rxiQ1R`7)?*^-Ap zw9I=oAa)#?34CxCasEhG-O&#Xx^=CrZ&m8U!ujiwELJhC-7FHvj&74tjFeg>0>?=$ z5u5}UpF0#^Jh93c;-q_=@Dzcz zXxg!a;Axa1jvLHn>VJkYA2S>%%J@Ui-;Q^=Gz#3DxN={W_?jLps3%74-d~XQX24!b z^tjGpdm$n&XM#dbZc%=P&4~a1#E*u541X;zH$#fP-4Ifd?BHK5Tu8p-exEO|Xtn%H z;tlOD7|iv|zD07xbf?s;3W^rt@KbW^=8xl;72zkyPbvoZE#X^)M+r&7V}x%LDiEeU zoz0mJ>)rGnQet{)HuGard!6t*!X@!wHe6pUVQODbkhNhK$l{G`+v1`7KhsDHvKGchPxQ4*^)mabI4yj4Y zp3cad^Zooav45czPxsVh&H@yO}j=*q>@k9vE_id(Go)R_{fQ!3sx03THxNm0GDJs^|y^@{O`{-uL;*FEuKHwD`I_4cAa-(A|re_gn; zG~`5wz9{5HGJ!3G_n!^Zg_lp_?xb}_Oev$xsL3=KkuuYrQPSD?o-rdOnADS3M4>L9H=c zn0z2(E4^mx&z=&SUKo96%*)Hg00fuAEH-jCO922nMg?O4 delta 20 acmeA(?K9>6%*)Hg00gtGj5cyNO922k_yq|7 diff --git a/routes/__pycache__/rooms.cpython-313.pyc b/routes/__pycache__/rooms.cpython-313.pyc index 8a6e38e73b9bb37257ef90eaf681e9f00d4a68dc..9066e79833d1b09e681a48da3dc26b5d5ef9b0e7 100644 GIT binary patch delta 23 dcmdl}x~G)yGcPX}0}w>VS!777Z{%BN1prxD2Fd^c delta 23 dcmdl}x~G)yGcPX}0}#mUGR= start_date) + if user_id: + query = query.filter_by(user_id=user_id) + + # Get total count for pagination + total_events = query.count() + total_pages = (total_events + per_page - 1) // per_page + + # Get paginated events + events = query.order_by(Event.timestamp.desc()).paginate(page=page, per_page=per_page) + + # Get all users for filter dropdown + users = User.query.order_by(User.username).all() + + return render_template('settings/tabs/events.html', + events=events.items, + total_pages=total_pages, + current_page=page, + event_type=event_type, + date_range=date_range, + user_id=user_id, + users=users, + csrf_token=session.get('csrf_token')) + + @main_bp.route('/api/events/') + @login_required + def get_event_details(event_id): + if not current_user.is_admin: + return jsonify({'error': 'Unauthorized'}), 403 + + event = Event.query.get_or_404(event_id) + return jsonify({ + 'id': event.id, + 'event_type': event.event_type, + 'user': { + 'id': event.user.id, + 'username': event.user.username, + 'last_name': event.user.last_name + }, + 'timestamp': event.timestamp.isoformat(), + 'details': event.details, + 'ip_address': event.ip_address, + 'user_agent': event.user_agent + }) \ No newline at end of file diff --git a/static/js/events.js b/static/js/events.js new file mode 100644 index 0000000..eee460b --- /dev/null +++ b/static/js/events.js @@ -0,0 +1,95 @@ +document.addEventListener('DOMContentLoaded', function() { + // Initialize variables + let currentPage = 1; + const totalPages = parseInt(document.getElementById('totalPages').textContent); + + // Get filter elements + const eventTypeFilter = document.getElementById('eventTypeFilter'); + const dateRangeFilter = document.getElementById('dateRangeFilter'); + const userFilter = document.getElementById('userFilter'); + const applyFiltersBtn = document.getElementById('applyFilters'); + + // Get pagination elements + const prevPageBtn = document.getElementById('prevPage'); + const nextPageBtn = document.getElementById('nextPage'); + const currentPageSpan = document.getElementById('currentPage'); + + // Event details modal + const eventDetailsModal = document.getElementById('eventDetailsModal'); + const eventDetailsContent = document.getElementById('eventDetailsContent'); + + // Function to update URL with current filters + function updateURL() { + const params = new URLSearchParams(window.location.search); + params.set('page', currentPage); + if (eventTypeFilter.value) params.set('event_type', eventTypeFilter.value); + if (dateRangeFilter.value) params.set('date_range', dateRangeFilter.value); + if (userFilter.value) params.set('user_id', userFilter.value); + window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`); + } + + // Function to load events with current filters + function loadEvents() { + const params = new URLSearchParams(); + params.set('page', currentPage); + if (eventTypeFilter.value) params.set('event_type', eventTypeFilter.value); + if (dateRangeFilter.value) params.set('date_range', dateRangeFilter.value); + if (userFilter.value) params.set('user_id', userFilter.value); + + window.location.href = `${window.location.pathname}?${params.toString()}`; + } + + // Function to load event details + function loadEventDetails(eventId) { + fetch(`/api/events/${eventId}`) + .then(response => response.json()) + .then(data => { + const formattedDetails = JSON.stringify(data.details, null, 2); + eventDetailsContent.textContent = formattedDetails; + }) + .catch(error => { + console.error('Error loading event details:', error); + eventDetailsContent.textContent = 'Error loading event details'; + }); + } + + // Event listeners for filters + applyFiltersBtn.addEventListener('click', function() { + currentPage = 1; + loadEvents(); + }); + + // Event listeners for pagination + prevPageBtn.addEventListener('click', function() { + if (currentPage > 1) { + currentPage--; + loadEvents(); + } + }); + + nextPageBtn.addEventListener('click', function() { + if (currentPage < totalPages) { + currentPage++; + loadEvents(); + } + }); + + // Event listener for event details modal + eventDetailsModal.addEventListener('show.bs.modal', function(event) { + const button = event.relatedTarget; + const eventId = button.getAttribute('data-event-id'); + loadEventDetails(eventId); + }); + + // Initialize filters from URL parameters + const urlParams = new URLSearchParams(window.location.search); + if (urlParams.has('event_type')) eventTypeFilter.value = urlParams.get('event_type'); + if (urlParams.has('date_range')) dateRangeFilter.value = urlParams.get('date_range'); + if (urlParams.has('user_id')) userFilter.value = urlParams.get('user_id'); + if (urlParams.has('page')) currentPage = parseInt(urlParams.get('page')); + + // Update pagination buttons state + prevPageBtn.disabled = currentPage === 1; + nextPageBtn.disabled = currentPage === totalPages; + currentPageSpan.textContent = currentPage; +}); \ No newline at end of file diff --git a/templates/settings/settings.html b/templates/settings/settings.html index d75f4b9..94e81c6 100644 --- a/templates/settings/settings.html +++ b/templates/settings/settings.html @@ -4,6 +4,7 @@ {% from "settings/tabs/company_info.html" import company_info_tab %} {% from "settings/tabs/security.html" import security_tab %} {% from "settings/tabs/debugging.html" import debugging_tab %} +{% from "settings/tabs/events.html" import events_tab %} {% from "settings/components/reset_colors_modal.html" import reset_colors_modal %} {% block title %}Settings - DocuPulse{% endblock %} @@ -41,6 +42,11 @@ Security +