Skip to content

Commit

Permalink
update export file access (#6112)
Browse files Browse the repository at this point in the history
* update export file access

* optimize

* update

* update

* optimeze code

* optimize

* Update utils.py

* Update utils.py

* optimize code

* update

* update

* optimize code

---------

Co-authored-by: 孙永强 <[email protected]>
Co-authored-by: r350178982 <[email protected]>
  • Loading branch information
3 people authored Jul 10, 2024
1 parent fbda14c commit a27f6d3
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 283 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, FormGroup, Label, Input, Alert } from 'reactstrap';
import { gettext, siteRoot } from '../../../utils/constants';
import { systemAdminAPI } from '../../../utils/system-admin-api';
import toaster from '../../../components/toast';
import { Utils } from '../../../utils/utils';
import moment from 'moment';

class LogsExportExcelDialog extends React.Component {
Expand All @@ -13,32 +16,73 @@ class LogsExportExcelDialog extends React.Component {
startDateStr: '',
endDateStr: '',
errMsg: '',
taskId: '',
};
}

downloadExcel = () => {
if (!this.isValidDateStr()) {
return;
}
let { startDateStr, endDateStr } = this.state;
let url = siteRoot;

switch (this.props.logType) {
case 'login':
url += 'sys/loginadmin/export-excel/';
this.sysExportLogs('loginadmin');
break;
case 'fileAccess':
url += 'sys/log/fileaudit/export-excel/';
this.sysExportLogs('fileaudit');
break;
case 'fileUpdate':
url += 'sys/log/fileupdate/export-excel/';
this.sysExportLogs('fileupdate');
break;
case 'sharePermission':
url += 'sys/log/permaudit/export-excel/';
this.sysExportLogs('permaudit');
break;
}
location.href = url + '?start=' + startDateStr + '&end=' + endDateStr;
this.props.toggle();
};

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 systemAdminAPI.queryAsyncOperationExportExcel(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(() => {
systemAdminAPI.queryAsyncOperationExportExcel(task_id).then(res => {
if (res.data.is_finished === true){
this.setState({isFinished: true});
clearInterval(this.timer);
location.href = siteRoot + 'sys/log/export-excel/?task_id=' + task_id + '&log_type=' + logType;
}
}).catch(err => {
if (this.state.isFinished === false){
clearInterval(this.timer);
toaster.danger(gettext('Failed to export. Please check whether the size of table attachments exceeds the limit.'));
}
});
}, 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);
} else {
toaster.danger(gettext('Internal Server Error.'));
}
} else {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
}
});
};

isValidDateStr = () => {
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/utils/system-admin-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ class SystemAdminAPI {
return this.req.get(url, {params: params});
}

sysAdminExportLogsExcel(start, end, logType) {
const url = this.server + '/api/v2.1/admin/logs/export-excel/';
const params = {
start: start,
end: end,
logType: logType
};
return this.req.get(url, { params: params });
}

queryAsyncOperationExportExcel(task_id) {
const url = this.server + '/api/v2.1/query-export-status/?task_id=' + task_id;
return this.req.get(url);
}

}

let systemAdminAPI = new SystemAdminAPI();
Expand Down
102 changes: 102 additions & 0 deletions seahub/api2/endpoints/admin/logs_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import os
import logging
import time
import json
from shutil import rmtree
from django.http import FileResponse
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from urllib.parse import quote

from seahub.api2.authentication import TokenAuthentication
from seahub.api2.endpoints.utils import check_time_period_valid, export_logs_to_excel, event_export_status
from seahub.api2.permissions import IsProVersion
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


class SysLogsExport(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAdminUser, IsProVersion)
throttle_classes = (UserRateThrottle,)

def get(self, request):
start = request.GET.get('start', None)
end = request.GET.get('end', None)
log_type = request.GET.get('logType', None)

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)

task_id = export_logs_to_excel(start, end, log_type)
res_data = {'task_id': task_id}
return Response(res_data)


class FileLogsExportStatus(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAdminUser, IsProVersion)
throttle_classes = (UserRateThrottle,)

def get(self, request):
"""
Get task status by task id
"""
task_id = request.GET.get('task_id', '')
if not task_id:
error_msg = 'task_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

resp = event_export_status(task_id)
if resp.status_code == 500:
logger.error('query export status error: %s, %s' % (task_id, resp.content))
return api_error(500, 'Internal Server Error')
if not resp.status_code == 200:
return api_error(resp.status_code, resp.content)

is_finished = json.loads(resp.content)['is_finished']

return Response({'is_finished': is_finished})


@login_required
@sys_staff_required
def sys_log_export_excel(request):
task_id = request.GET.get('task_id', None)
log_type = request.GET.get('log_type', None)

if not task_id:
error_msg = 'task_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

if log_type == 'loginadmin':
excel_name = 'login-logs.xlsx'
elif log_type == 'fileaudit':
excel_name = 'file-access-logs.xlsx'
elif log_type == 'fileupdate':
excel_name = 'file-update-logs.xlsx'
elif log_type == 'permaudit':
excel_name = 'perm-audit-logs.xlsx'
else:
error_msg = 'log_type invalid'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

target_dir = os.path.join('/tmp/seafile_events/', task_id)
tmp_excel_path = os.path.join(target_dir, excel_name)
if not os.path.isfile(tmp_excel_path):
return api_error(status.HTTP_400_BAD_REQUEST, excel_name + ' not found.')

response = FileResponse(open(tmp_excel_path, 'rb'), content_type='application/ms-excel', as_attachment=True)
try:
rmtree(target_dir)
except OSError:
pass
response['Content-Disposition'] = 'attachment;filename*=UTF-8\'\'' + quote(excel_name)

return response
36 changes: 35 additions & 1 deletion seahub/api2/endpoints/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
import logging
import requests
import json
import datetime
import urllib.request
import urllib.parse
Expand All @@ -18,7 +19,8 @@
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
from seahub.utils import get_log_events_by_time, is_pro_version, is_org_context

from seahub.settings import SEADOC_PRIVATE_KEY, FILE_CONVERTER_SERVER_URL
from seahub.settings import SEADOC_PRIVATE_KEY, FILE_CONVERTER_SERVER_URL, SECRET_KEY, \
SEAFEVENTS_SERVER_URL

try:
from seahub.settings import MULTI_TENANCY
Expand Down Expand Up @@ -282,3 +284,35 @@ def sdoc_export_to_docx(path, username, doc_uuid, download_token,
resp = requests.post(url, json=params, headers=headers, timeout=30)

return resp


def format_date(start, end):
start_struct_time = datetime.datetime.strptime(start, "%Y-%m-%d")
start_timestamp = time.mktime(start_struct_time.timetuple())

end_struct_time = datetime.datetime.strptime(end, "%Y-%m-%d")
end_timestamp = time.mktime(end_struct_time.timetuple())
end_timestamp += 24 * 60 * 60
return start_timestamp, end_timestamp


def export_logs_to_excel(start, end, log_type):
start_time, end_time = format_date(start, end)
payload = {'exp': int(time.time()) + 300, }
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
headers = {"Authorization": "Token %s" % token}
url = urljoin(SEAFEVENTS_SERVER_URL, '/add-init-export-log-task')
params = {'start_time': start_time, 'end_time': end_time, 'log_type': log_type}
resp = requests.get(url, params=params, headers=headers)
return json.loads(resp.content)['task_id']


def event_export_status(task_id):
payload = {'exp': int(time.time()) + 300, }
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
headers = {"Authorization": "Token %s" % token}
url = urljoin(SEAFEVENTS_SERVER_URL, '/query-export-status')
params = {'task_id': task_id}
resp = requests.get(url, params=params, headers=headers)

return resp
Loading

0 comments on commit a27f6d3

Please sign in to comment.