From 0d877b2287823b5501ceaccad5d0296eaa7ee2ca Mon Sep 17 00:00:00 2001 From: awu0403 <76416779+awu0403@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:50:56 +0800 Subject: [PATCH] fix export file access log (#6944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix * update * optimize export log * update * update * update * fomrat-update --------- Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com> Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com> --- .../org-admin-logs-export-excel-dialog.js | 160 ++++++++++------- .../src/components/dialog/seahub-io-dialog.js | 39 +++++ .../sysadmin-logs-export-excel-dialog.js | 163 +++++++++++------- frontend/src/css/seahub-io-dialog.css | 12 ++ seahub/api2/endpoints/admin/logs_export.py | 12 ++ seahub/organizations/org_logs_export.py | 11 ++ seahub/settings.py | 3 + 7 files changed, 278 insertions(+), 122 deletions(-) create mode 100644 frontend/src/components/dialog/seahub-io-dialog.js create mode 100644 frontend/src/css/seahub-io-dialog.css diff --git a/frontend/src/components/dialog/org-admin-logs-export-excel-dialog.js b/frontend/src/components/dialog/org-admin-logs-export-excel-dialog.js index 0525b1c022..c5a4de895b 100644 --- a/frontend/src/components/dialog/org-admin-logs-export-excel-dialog.js +++ b/frontend/src/components/dialog/org-admin-logs-export-excel-dialog.js @@ -7,6 +7,8 @@ import { orgAdminAPI } from '../../utils/org-admin-api'; import { userAPI } from '../../utils/user-api'; import toaster from '../../components/toast'; import { Utils } from '../../utils/utils'; +import SeahubIODialog from '../dialog/seahub-io-dialog'; + class OrgLogsExportExcelDialog extends React.Component { @@ -18,6 +20,7 @@ class OrgLogsExportExcelDialog extends React.Component { endDateStr: '', errMsg: '', taskId: '', + isShowIODialog: false, }; } @@ -38,46 +41,66 @@ class OrgLogsExportExcelDialog extends React.Component { } }; + queryIOStatus = (task_id, logType) => { + userAPI.queryIOStatus(task_id).then(res => { + if (res.data.is_finished === true) { + this.setState({ + isShowIODialog: false + }); + this.props.toggle(); + location.href = siteRoot + 'api/v2.1/org/admin/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; + } else { + setTimeout(() => { + this.queryIOStatus(task_id, logType); + }, 1000); + } + }).catch(err => { + this.setState({ + isShowIODialog: false + }); + this.props.toggle(); + toaster.danger(gettext('Failed to export. Please check whether the size of table attachments exceeds the limit.')); + }); + }; + orgAdminExportLogs = (logType) => { let { startDateStr, endDateStr } = this.state; let task_id = ''; - orgAdminAPI.orgAdminExportLogsExcel(orgID, startDateStr, endDateStr, logType).then(res => { - task_id = res.data.task_id; - this.setState({ - taskId: task_id - }); - this.props.toggle(); - return userAPI.queryIOStatus(task_id); - }).then(res => { - if (res.data.is_finished === true) { - location.href = siteRoot + 'api/v2.1/org/admin/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; - } else { - this.timer = setInterval(() => { - userAPI.queryIOStatus(task_id).then(res => { - if (res.data.is_finished === true) { - clearInterval(this.timer); - location.href = siteRoot + 'api/v2.1/org/admin/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; - } - }).catch(err => { - clearInterval(this.timer); - toaster.danger(gettext('Failed to export. Please check whether the size of table attachments exceeds the limit.')); + this.setState({ + isShowIODialog: true + }, () => { + orgAdminAPI.orgAdminExportLogsExcel(orgID, startDateStr, endDateStr, logType).then(res => { + task_id = res.data.task_id; + this.setState({ + taskId: task_id + }); + return userAPI.queryIOStatus(task_id); + }).then(res => { + if (res.data.is_finished === true) { + this.setState({ + isShowIODialog: false }); - }, 1000); - } - }).catch(error => { - this.props.toggle(); - if (error.response && error.response.status === 500) { - const error_msg = error.response.data ? error.response.data['error_msg'] : null; - if (error_msg && error_msg !== 'Internal Server Error') { - toaster.danger(error_msg); + this.props.toggle(); + location.href = siteRoot + 'api/v2.1/org/admin/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; } else { - toaster.danger(gettext('Internal Server Error')); + this.queryIOStatus(task_id, logType); } - } else { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - } + }).catch(error => { + if (error.response && error.response.status === 500) { + const error_msg = error.response.data ? error.response.data['error_msg'] : null; + if (error_msg && error_msg !== 'Internal Server Error') { + toaster.danger(error_msg); + } else { + toaster.danger(gettext('Internal Server Error')); + } + } else { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + } + this.props.toggle(); + }); }); + }; isValidDateStr = () => { @@ -111,39 +134,54 @@ class OrgLogsExportExcelDialog extends React.Component { }); }; + onExportToggle = (e) => { + this.setState({ + isShowIODialog: !this.state.isShowIODialog, + }); + this.props.toggle(); + }; + render() { return ( - - {gettext('Choose date')} - - - {gettext('Start date')} - - - - {gettext('End date')} - - - {this.state.errMsg && + + {!this.state.isShowIODialog && + + {gettext('Choose date')} + + + {gettext('Start date')} + + + + {gettext('End date')} + + + {this.state.errMsg && {gettext(this.state.errMsg)} - } - - - {gettext('Cancel')} - {gettext('Submit')} - - + } + + + {gettext('Cancel')} + {gettext('Submit')} + + } + {this.state.isShowIODialog && + + } + ); } } diff --git a/frontend/src/components/dialog/seahub-io-dialog.js b/frontend/src/components/dialog/seahub-io-dialog.js new file mode 100644 index 0000000000..520c4a197f --- /dev/null +++ b/frontend/src/components/dialog/seahub-io-dialog.js @@ -0,0 +1,39 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Modal, ModalBody, ModalHeader } from 'reactstrap'; +import { gettext } from '../../utils/constants'; +import Loading from '../loading'; + +import '../../css/seahub-io-dialog.css'; + + +const propTypes = { + toggle: PropTypes.func.isRequired, +}; + +class SeahubIODialog extends React.Component { + + toggle = () => { + this.props.toggle(); + }; + + render() { + return ( + + + {gettext('Exporting')} + + + <> + + {gettext('Exporting...')} + > + + + ); + } +} + +SeahubIODialog.propTypes = propTypes; + +export default SeahubIODialog; diff --git a/frontend/src/components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog.js b/frontend/src/components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog.js index 568d712fb6..4909eabb98 100644 --- a/frontend/src/components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog.js +++ b/frontend/src/components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog.js @@ -7,6 +7,7 @@ import { systemAdminAPI } from '../../../utils/system-admin-api'; import { userAPI } from '../../../utils/user-api'; import toaster from '../../../components/toast'; import { Utils } from '../../../utils/utils'; +import SeahubIODialog from '../../dialog/seahub-io-dialog'; class LogsExportExcelDialog extends React.Component { @@ -18,6 +19,7 @@ class LogsExportExcelDialog extends React.Component { endDateStr: '', errMsg: '', taskId: '', + isShowIODialog: false, }; } @@ -41,45 +43,67 @@ class LogsExportExcelDialog extends React.Component { } }; + queryIOStatus = (task_id, logType) => { + userAPI.queryIOStatus(task_id).then(res => { + if (res.data.is_finished === true) { + this.setState({ + isShowIODialog: false + }); + this.props.toggle(); + location.href = siteRoot + 'sys/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; + + } else { + setTimeout(() => { + this.queryIOStatus(task_id, logType); + }, 1000); + } + }).catch(err => { + this.setState({ + isShowIODialog: false + }); + toaster.danger(gettext('Failed to export. Please check whether the size of table attachments exceeds the limit.')); + }); + }; + sysExportLogs = (logType) => { let { startDateStr, endDateStr } = this.state; let task_id = ''; - systemAdminAPI.sysAdminExportLogsExcel(startDateStr, endDateStr, logType).then(res => { - task_id = res.data.task_id; - this.setState({ - taskId: task_id - }); - this.props.toggle(); - return userAPI.queryIOStatus(task_id); - }).then(res => { - if (res.data.is_finished === true) { - location.href = siteRoot + 'sys/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; - } else { - this.timer = setInterval(() => { - userAPI.queryIOStatus(task_id).then(res => { - if (res.data.is_finished === true) { - clearInterval(this.timer); - location.href = siteRoot + 'sys/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; - } - }).catch(err => { - clearInterval(this.timer); - toaster.danger(gettext('Failed to export. Please check whether the size of table attachments exceeds the limit.')); + this.setState({ + isShowIODialog: true + }, () => { + systemAdminAPI.sysAdminExportLogsExcel(startDateStr, endDateStr, logType).then(res => { + task_id = res.data.task_id; + this.setState({ + taskId: task_id, + }); + return userAPI.queryIOStatus(task_id); + }).then(res => { + if (res.data.is_finished === true) { + this.setState({ + isShowIODialog: false, }); - }, 1000); - } - }).catch(error => { - this.props.toggle(); - if (error.response && error.response.status === 500) { - const error_msg = error.response.data ? error.response.data['error_msg'] : null; - if (error_msg && error_msg !== 'Internal Server Error') { - toaster.danger(error_msg); + this.props.toggle(); + location.href = siteRoot + 'sys/log/export-excel/?task_id=' + task_id + '&log_type=' + logType; } else { - toaster.danger(gettext('Internal Server Error')); + this.queryIOStatus(task_id, logType); } - } else { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - } + }).catch(error => { + if (error.response && error.response.status === 500) { + const error_msg = error.response.data ? error.response.data['error_msg'] : null; + if (error_msg && error_msg !== 'Internal Server Error') { + toaster.danger(error_msg); + } else { + toaster.danger(gettext('Internal Server Error')); + } + } else { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + } + this.setState({ + isShowIODialog: false + }); + this.props.toggle(); + }); }); }; @@ -114,39 +138,56 @@ class LogsExportExcelDialog extends React.Component { }); }; + onExportToggle = (e) => { + this.setState({ + isShowIODialog: !this.state.isShowIODialog, + }); + this.props.toggle(); + }; + render() { return ( - - {gettext('Choose date')} - - - {gettext('Start date')} - - - - {gettext('End date')} - - - {this.state.errMsg && + + {!this.state.isShowIODialog && + + {gettext('Choose date')} + + + {gettext('Start date')} + + + + {gettext('End date')} + + + {this.state.errMsg && {gettext(this.state.errMsg)} - } - - - {gettext('Cancel')} - {gettext('Submit')} - - + } + + + {gettext('Cancel')} + {gettext('Submit')} + + + + } + {this.state.isShowIODialog && + + } + ); } } diff --git a/frontend/src/css/seahub-io-dialog.css b/frontend/src/css/seahub-io-dialog.css new file mode 100644 index 0000000000..333a4cdd60 --- /dev/null +++ b/frontend/src/css/seahub-io-dialog.css @@ -0,0 +1,12 @@ + +.seahub-io-dialog .modal-body { + height: 142px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.seahub-io-dialog .modal-body .seahub-io-dialog-parsing-text { + text-align: center; + margin-top: 14px; +} diff --git a/seahub/api2/endpoints/admin/logs_export.py b/seahub/api2/endpoints/admin/logs_export.py index 93aeae0c2c..9e8d993e11 100644 --- a/seahub/api2/endpoints/admin/logs_export.py +++ b/seahub/api2/endpoints/admin/logs_export.py @@ -1,5 +1,6 @@ import os from shutil import rmtree +from datetime import datetime from django.http import FileResponse from rest_framework.authentication import SessionAuthentication from rest_framework.permissions import IsAdminUser @@ -16,6 +17,8 @@ from seahub.api2.throttling import UserRateThrottle from seahub.api2.utils import api_error from seahub.auth.decorators import login_required from seahub.base.decorators import sys_staff_required +from seahub.settings import ADMIN_LOGS_EXPORT_MAX_DAYS + class SysLogsExport(APIView): @@ -32,6 +35,15 @@ class SysLogsExport(APIView): error_msg = 'Failed to export excel, invalid start or end date.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + start_date = datetime.strptime(start, '%Y-%m-%d') + end_date = datetime.strptime(end, '%Y-%m-%d') + if start_date > end_date: + error_msg = 'invalid start or end date' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + if (end_date - start_date).days > ADMIN_LOGS_EXPORT_MAX_DAYS: + error_msg = 'Failed to export excel, only can export logs within %s days' % ADMIN_LOGS_EXPORT_MAX_DAYS + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + task_id = export_logs_to_excel(start, end, log_type) res_data = {'task_id': task_id} return Response(res_data) diff --git a/seahub/organizations/org_logs_export.py b/seahub/organizations/org_logs_export.py index 6e3710bae8..532b966180 100644 --- a/seahub/organizations/org_logs_export.py +++ b/seahub/organizations/org_logs_export.py @@ -1,6 +1,7 @@ import os import logging from shutil import rmtree +from datetime import datetime from django.http import FileResponse from rest_framework.authentication import SessionAuthentication from rest_framework.response import Response @@ -17,6 +18,7 @@ from seahub.api2.utils import api_error from seahub.auth.decorators import login_required from seahub.organizations.api.permissions import IsOrgAdmin from seahub.organizations.decorators import org_staff_required +from seahub.settings import ADMIN_LOGS_EXPORT_MAX_DAYS @@ -35,6 +37,15 @@ class OrgLogsExport(APIView): if not check_time_period_valid(start, end): error_msg = 'Failed to export excel, invalid start or end date.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + start_date = datetime.strptime(start, '%Y-%m-%d') + end_date = datetime.strptime(end, '%Y-%m-%d') + if start_date > end_date: + error_msg = 'invalid start or end date' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + if (end_date - start_date).days > ADMIN_LOGS_EXPORT_MAX_DAYS: + error_msg = 'Failed to export excel, only can export logs within %s days' % ADMIN_LOGS_EXPORT_MAX_DAYS + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) task_id = export_logs_to_excel(start, end, log_type, org_id) res_data = {'task_id': task_id} return Response(res_data) diff --git a/seahub/settings.py b/seahub/settings.py index 6ee534d8af..19e8016852 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -494,6 +494,9 @@ ENABLE_SEAFILE_DOCS = False ENABLE_CONVERT_TO_TEAM_ACCOUNT = False + +ADMIN_LOGS_EXPORT_MAX_DAYS = 180 + # File preview FILE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024 FILE_ENCODING_LIST = ['auto', 'utf-8', 'gbk', 'ISO-8859-1', 'ISO-8859-5']