1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-01 23:38:37 +00:00

file scan records page (#3051)

* file scan records page

* add file scan setting

* repair code
This commit is contained in:
王健辉 2019-03-13 16:50:30 +08:00 committed by Daniel Pan
parent 53c3791043
commit 8c81489c51
17 changed files with 611 additions and 2 deletions

View File

@ -143,7 +143,12 @@ module.exports = {
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/view-file-umind.js",
]
],
sysAdmin: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/pages/sys-admin",
],
},
output: {

View File

@ -77,6 +77,7 @@ module.exports = {
viewFilePDF: [require.resolve('./polyfills'), paths.appSrc + "/view-file-pdf.js"],
orgAdmin: [require.resolve('./polyfills'), paths.appSrc + "/pages/org-admin"],
viewFileUMind: [require.resolve('./polyfills'), paths.appSrc + "/view-file-umind.js"],
sysAdmin: [require.resolve('./polyfills'), paths.appSrc + "/pages/sys-admin"],
},
output: {

View File

@ -1,9 +1,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { Utils } from '../../utils/utils';
import editorUtilities from '../../utils/editor-utilties';
import { siteRoot, gettext } from '../../utils/constants';
const propTypes = {
isAdminPanel: PropTypes.bool,
};
class Account extends Component {
constructor(props) {
super(props);
@ -87,11 +92,16 @@ class Account extends Component {
}
renderMenu = () => {
if(this.state.isStaff){
if (this.state.isStaff && !this.props.isAdminPanel) {
return (
<a href={siteRoot + 'sys/useradmin/'} title={gettext('System Admin')} className="item">{gettext('System Admin')}</a>
);
}
if (this.props.isAdminPanel) {
return (
<a href={siteRoot} title={gettext('Exit Admin Panel')} className="item">{gettext('Exit Admin Panel')}</a>
);
}
if (this.state.isOrgStaff) {
return (
<a href={siteRoot + 'org/useradmin/'} title={gettext('Organization Admin')} className="item">{gettext('Organization Admin')}</a>
@ -143,4 +153,6 @@ class Account extends Component {
}
}
Account.propTypes = propTypes;
export default Account;

View File

@ -0,0 +1,137 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { seafileAPI } from '../../utils/seafile-api';
import { gettext, loginUrl } from '../../utils/constants';
const tablePropTypes = {
loading: PropTypes.bool.isRequired,
errorMsg: PropTypes.string.isRequired,
records: PropTypes.array.isRequired,
};
class Table extends Component {
render() {
let { loading, errorMsg, records } = this.props;
if (loading) {
return <span className="loading-icon loading-tip"></span>;
} else if (errorMsg) {
return <p className="error text-center">{errorMsg}</p>;
} else {
return (
<table width="100%" className="table table-hover table-vcenter">
<thead>
<tr>
<th width="16%">{gettext('Library')}</th>
<th width="30%">{gettext('ID')}</th>
<th width="30%">{gettext('Path')}</th>
<th width="12%">{gettext('Label')}</th>
<th width="12%">{gettext('Suggestion')}</th>
</tr>
</thead>
<tbody>
{records.map((record, index) => {
return (
<Item key={index} record={record} />
);
})}
</tbody>
</table>
);
}
}
}
Table.propTypes = tablePropTypes;
const itemPropTypes = {
record: PropTypes.object.isRequired,
};
class Item extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
let record = this.props.record;
return (
<tr>
<td>{record.repo_name}</td>
<td>{record.repo_id}</td>
<td>{record.path}</td>
<td>{record.detail.label}</td>
<td>{record.detail.suggestion}</td>
</tr>
);
}
}
Item.propTypes = itemPropTypes;
class FileScanRecords extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
errorMsg: '',
records: [],
};
}
componentDidMount() {
seafileAPI.listFileScanRecords().then((res) => {
this.setState({
loading: false,
records: res.data.record_list,
});
}).catch((error) => {
if (error.response) {
if (error.response.status == 403) {
this.setState({
loading: false,
errorMsg: gettext('Permission denied')
});
location.href = `${loginUrl}?next=${encodeURIComponent(location.href)}`;
} else {
this.setState({
loading: false,
errorMsg: gettext('Error')
});
}
} else {
this.setState({
loading: false,
errorMsg: gettext('Please check the network.')
});
}
});
}
render() {
return (
<div className="main-panel-center">
<div className="cur-view-container" id="content-scan-records">
<div className="cur-view-path">
<h3 className="sf-heading">{gettext('Content Scan Records')}</h3>
</div>
<div className="cur-view-content">
<Table
loading={this.state.loading}
errorMsg={this.state.errorMsg}
records={this.state.records}
/>
</div>
</div>
</div>
);
}
}
export default FileScanRecords;

View File

@ -0,0 +1,60 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from '@reach/router';
import { siteRoot, gettext } from '../../utils/constants';
import SidePanel from './side-panel';
import MainPanel from './main-panel';
import FileScanRecords from './file-scan-records';
import '../../assets/css/fa-solid.css';
import '../../assets/css/fa-regular.css';
import '../../assets/css/fontawesome.css';
import '../../css/layout.css';
import '../../css/toolbar.css';
class SysAdmin extends React.Component {
constructor(props) {
super(props);
this.state = {
isSidePanelClosed: false,
currentTab: 'file-scan',
};
}
componentDidMount() {
let href = window.location.href.split('/');
this.setState({currentTab: href[href.length - 2]});
}
onCloseSidePanel = () => {
this.setState({isSidePanelClosed: !this.state.isSidePanelClosed});
}
tabItemClick = (param) => {
this.setState({currentTab: param});
}
render() {
let { currentTab, isSidePanelClosed, } = this.state;
return (
<div id="main">
<SidePanel isSidePanelClosed={isSidePanelClosed} onCloseSidePanel={this.onCloseSidePanel} />
<MainPanel>
<Router>
<FileScanRecords
path={siteRoot + 'sys/file-scan-records'}
currentTab={currentTab}
tabItemClick={this.tabItemClick}
/>
</Router>
</MainPanel>
</div>
);
}
}
ReactDOM.render(
<SysAdmin />,
document.getElementById('wrapper')
);

View File

@ -0,0 +1,31 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Account from '../../components/common/account';
const propTypes = {
children: PropTypes.object.isRequired,
};
class MainPanel extends Component {
render() {
return (
<div className="main-panel o-hidden">
<div className="main-panel-north border-left-show">
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu"></span>
</div>
<div className="common-toolbar">
<Account isAdminPanel={true} />
</div>
</div>
{this.props.children}
</div>
);
}
}
MainPanel.propTypes = propTypes;
export default MainPanel;

View File

@ -0,0 +1,183 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from '@reach/router';
import Logo from '../../components/logo';
import { gettext, siteRoot, isPro, isDefaultAdmin, canViewSystemInfo, canViewStatistic,
canConfigSystem, canManageLibrary, canManageUser, canManageGroup, canViewUserLog,
canViewAdminLog, constanceEnabled, multiTenancy, multiInstitution, sysadminExtraEnabled,
enableGuestInvitation, enableTermsAndConditions, enableFileScan } from '../../utils/constants';
const propTypes = {
isSidePanelClosed: PropTypes.bool.isRequired,
onCloseSidePanel: PropTypes.func.isRequired,
};
class SidePanel extends React.Component {
render() {
return (
<div className={`side-panel ${this.props.isSidePanelClosed ? '' : 'left-zero'}`}>
<div className="side-panel-north">
<Logo onCloseSidePanel={this.props.onCloseSidePanel}/>
</div>
<div className="side-panel-center">
<div className="side-nav">
<div className="side-nav-con">
<h3 className="sf-heading">{gettext('System Admin')}</h3>
<ul className="nav nav-pills flex-column nav-container">
{canViewSystemInfo &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#dashboard/"}>
<span className="sf2-icon-info" aria-hidden="true"></span>
<span className="nav-text">{gettext('Info')}</span>
</a>
</li>
}
{isPro && canViewStatistic &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/statistic/file/"}>
<span className="sf2-icon-histogram" aria-hidden="true"></span>
<span className="nav-text">{gettext('Statistic')}</span>
</a>
</li>
}
{isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#desktop-devices/"}>
<span className="sf2-icon-monitor" aria-hidden="true"></span>
<span className="nav-text">{gettext('Devices')}</span>
</a>
</li>
}
{constanceEnabled && canConfigSystem &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/settings/"}>
<span className="sf2-icon-cog2" aria-hidden="true"></span>
<span className="nav-text">{gettext('Settings')}</span>
</a>
</li>
}
{canManageLibrary &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#all-libs/"}>
<span className="sf2-icon-library" aria-hidden="true"></span>
<span className="nav-text">{gettext('Libraries')}</span>
</a>
</li>
}
{canManageUser &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/useradmin/"}>
<span className="sf2-icon-user" aria-hidden="true"></span>
<span className="nav-text">{gettext('Users')}</span>
</a>
</li>
}
{canManageGroup &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#groups/"}>
<span className="sf2-icon-group" aria-hidden="true"></span>
<span className="nav-text">{gettext('Groups')}</span>
</a>
</li>
}
{isPro && canManageGroup &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#address-book/"}>
<span className="sf2-icon-organization" aria-hidden="true"></span>
<span className="nav-text">{gettext('Departments')}</span>
</a>
</li>
}
{multiTenancy && isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/orgadmin/"}>
<span className="sf2-icon-organization" aria-hidden="true"></span>
<span className="nav-text">{gettext('Organizations')}</span>
</a>
</li>
}
{multiInstitution && isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/instadmin/"}>
<span className="sf2-icon-organization" aria-hidden="true"></span>
<span className="nav-text">{gettext('Institutions')}</span>
</a>
</li>
}
{isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/notificationadmin/"}>
<span className="sf2-icon-msgs" aria-hidden="true"></span>
<span className="nav-text">{gettext('Notifications')}</span>
</a>
</li>
}
{isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/publinkadmin/"}>
<span className="sf2-icon-link" aria-hidden="true"></span>
<span className="nav-text">{gettext('Links')}</span>
</a>
</li>
}
{sysadminExtraEnabled && canViewUserLog &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/loginadmin/"}>
<span className="sf2-icon-clock" aria-hidden="true"></span>
<span className="nav-text">{gettext('Logs')}</span>
</a>
</li>
}
{isPro && isDefaultAdmin && enableFileScan &&
<li className="nav-item">
<Link className='nav-link ellipsis' to={siteRoot + "sys/file-scan-records/"}>
<span className="sf2-icon-security" aria-hidden="true"></span>
<span className="nav-text">{gettext('File Scan')}</span>
</Link>
</li>
}
{isPro && isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/virus_scan_records/"}>
<span className="sf2-icon-security" aria-hidden="true"></span>
<span className="nav-text">{gettext('Virus Scan')}</span>
</a>
</li>
}
{enableGuestInvitation && isDefaultAdmin &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/invitationadmin/"}>
<span className="sf2-icon-invite" aria-hidden="true"></span>
<span className="nav-text">{gettext('Invitations')}</span>
</a>
</li>
}
{isDefaultAdmin && enableTermsAndConditions &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sys/termsadmin/"}>
<span className="sf2-icon-wiki" aria-hidden="true"></span>
<span className="nav-text">{gettext('Terms and Conditions')}</span>
</a>
</li>
}
{isPro && canViewAdminLog &&
<li className="nav-item">
<a className='nav-link ellipsis' href={siteRoot + "sysadmin/#admin-operation-logs/"}>
<span className="sf2-icon-admin-log" aria-hidden="true"></span>
<span className="nav-text">{gettext('Admin Logs')}</span>
</a>
</li>
}
</ul>
</div>
</div>
</div>
</div>
);
}
}
SidePanel.propTypes = propTypes;
export default SidePanel;

View File

@ -73,3 +73,21 @@ export const originFileExists = window.draft ? window.draft.config.originFileExi
// org admin
export const orgID = window.org ? window.org.pageOptions.orgID : '';
export const invitationLink = window.org ? window.org.pageOptions.invitationLink : '';
// sys admin
export const constanceEnabled = window.sysadmin ? window.sysadmin.pageOptions.constance_enabled : '';
export const multiTenancy = window.sysadmin ? window.sysadmin.pageOptions.multi_tenancy : '';
export const multiInstitution = window.sysadmin ? window.sysadmin.pageOptions.multi_institution : '';
export const sysadminExtraEnabled = window.sysadmin ? window.sysadmin.pageOptions.sysadmin_extra_enabled : '';
export const enableGuestInvitation = window.sysadmin ? window.sysadmin.pageOptions.enable_guest_invitation : '';
export const enableTermsAndConditions = window.sysadmin ? window.sysadmin.pageOptions.enable_terms_and_conditions : '';
export const isDefaultAdmin = window.sysadmin ? window.sysadmin.pageOptions.is_default_admin : '';
export const enableFileScan = window.sysadmin ? window.sysadmin.pageOptions.enable_file_scan : '';
export const canViewSystemInfo = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_view_system_info : '';
export const canViewStatistic = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_view_statistic : '';
export const canConfigSystem = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_config_system : '';
export const canManageLibrary = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_manage_library : '';
export const canManageUser = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_manage_user : '';
export const canManageGroup = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_manage_group : '';
export const canViewUserLog = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_view_user_log : '';
export const canViewAdminLog = window.sysadmin ? window.sysadmin.pageOptions.admin_permissions.can_view_admin_log : '';

View File

@ -52,6 +52,7 @@
-webkit-font-smoothing: antialiased;
}
.sf2-icon-histogram:before { content:"\e000"; }
.sf2-icon-wrench:before { content:"\e001"; }
.sf2-icon-clock:before { content:"\e002"; }
.sf2-icon-bell:before { content:"\e003"; }
@ -68,21 +69,26 @@
.sf2-icon-history:before { content:"\e014"; }
.sf2-icon-cog1:before { content:"\e015"; }
.sf2-icon-trash:before { content:"\e016"; }
.sf2-icon-security:before { content:"\e017"; }
.sf2-icon-tick:before { content:"\e01e"; }
.sf2-icon-x2:before { content:"\e01f"; }
.sf2-icon-edit:before { content:"\e018"; }
.sf2-icon-caret-down:before { content:"\e01a"; }
.sf2-icon-cog2:before { content:"\e01b"; }
.sf2-icon-x1:before { content:"\e01d"; }
.sf2-icon-minus:before {content:"\e01c"}
.sf2-icon-confirm:before {content:"\e01e"}
.sf2-icon-cancel:before {content:"\e01f"}
.sf2-icon-user2:before { content:"\e020"; }
.sf2-icon-msgs:before { content:"\e021"; }
.sf2-icon-grid-view:before { content:"\e025"; }
.sf2-icon-list-view:before { content:"\e026"; }
.sf2-icon-plus:before { content: "\e027"; }
.sf2-icon-copy:before {content:"\e028"}
.sf2-icon-move:before {content:"\e029"}
.sf2-icon-reply:before { content:"\e02a"; }
.sf2-icon-admin-log:before { content:"\e02e"; }
.sf2-icon-info:before { content:"\e02f"; }
.sf2-icon-menu:before { content: "\e031"; }
.sf2-icon-more:before { content: "\e032"; }
.sf2-icon-x3:before {content:"\e035";}

View File

@ -0,0 +1,64 @@
# Copyright (c) 2012-2016 Seafile Ltd.
import logging
import json
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 seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.permissions import IsProVersion
from seahub.api2.utils import api_error
from seahub.utils import get_file_scan_record
from seaserv import seafile_api
logger = logging.getLogger(__name__)
class AdminFileScanRecords(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAdminUser, IsProVersion)
throttle_classes = (UserRateThrottle,)
def get(self, request):
"""get file content scan records
"""
try:
page = int(request.GET.get('page', ''))
except ValueError:
page = 1
try:
per_page = int(request.GET.get('per_page', ''))
except ValueError:
per_page = 25
start = (page - 1) * per_page
count = per_page
try:
record_list = get_file_scan_record(start, count)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
for record in record_list:
repo = seafile_api.get_repo(record["repo_id"])
if not repo:
record["repo_name"] = ""
else:
record["repo_name"] = repo.name
record_detail = json.loads(record['detail'])
detail_dict = record_detail.values()[0]
detail = dict()
detail["suggestion"] = detail_dict["suggestion"]
detail["label"] = detail_dict["label"]
record["detail"] = detail
return Response({"record_list": record_list}, status=status.HTTP_200_OK)

View File

@ -44,6 +44,11 @@ try:
from seahub.settings import MULTI_TENANCY
except ImportError:
MULTI_TENANCY = False
try:
from seahub.settings import ENABLE_FILE_SCAN
except ImportError:
ENABLE_FILE_SCAN = False
def base(request):
"""
@ -120,6 +125,7 @@ def base(request):
'enable_upload_folder': dj_settings.ENABLE_UPLOAD_FOLDER,
'enable_resumable_fileupload': dj_settings.ENABLE_RESUMABLE_FILEUPLOAD,
'service_url': get_service_url().rstrip('/'),
'enable_file_scan': ENABLE_FILE_SCAN,
}
if request.user.is_staff:

View File

@ -258,6 +258,9 @@ INSTALLED_APPS = (
'seahub.related_files',
)
# Enable or disable view File Scan
# ENABLE_FILE_SCAN = True
# Enable or disable multiple storage backends.
ENABLE_STORAGE_CLASSES = False

View File

@ -94,6 +94,12 @@
</li>
{% endif %}
{% if is_pro and is_default_admin and enable_file_scan %}
<li class="tab {% block cur_file_scan %}{% endblock %}">
<a href="{{ SITE_ROOT }}sys/file-scan-records/"><span class="sf2-icon-security"></span>{% trans "File Scan" %}</a>
</li>
{% endif %}
{% if is_pro and is_default_admin %}
<li class="tab {% block cur_virus_scan %}{% endblock %}">
<a href="{{ SITE_ROOT }}sys/virus_scan_records/"><span class="sf2-icon-security"></span>{% trans "Virus Scan" %}</a>

View File

@ -0,0 +1,33 @@
{% extends "base_for_react.html" %}
{% load seahub_tags i18n %}
{% load render_bundle from webpack_loader %}
{% block extra_script %}
<script type="text/javascript">
window.sysadmin = {
config: {
},
pageOptions: {
constance_enabled: {% if constance_enabled %} true {% else %} false {% endif %},
multi_tenancy: {% if multi_tenancy %} true {% else %} false {% endif %},
multi_institution: {% if multi_institution %} true {% else %} false {% endif %},
sysadmin_extra_enabled: {% if sysadmin_extra_enabled %} true {% else %} false {% endif %},
enable_guest_invitation: {% if enable_guest_invitation %} true {% else %} false {% endif %},
enable_terms_and_conditions: {% if enable_terms_and_conditions %} true {% else %} false {% endif %},
is_default_admin: {% if is_default_admin %} true {% else %} false {% endif %},
enable_file_scan: {% if enable_file_scan %} true {% else %} false {% endif %},
admin_permissions: {
"can_view_system_info": {% if user.admin_permissions.can_view_system_info %} true {% else %} false {% endif %},
"can_view_statistic": {% if user.admin_permissions.can_view_statistic %} true {% else %} false {% endif %},
"can_config_system": {% if user.admin_permissions.can_config_system %} true {% else %} false {% endif %},
"can_manage_library": {% if user.admin_permissions.can_manage_library %} true {% else %} false {% endif %},
"can_manage_user": {% if user.admin_permissions.can_manage_user %} true {% else %} false {% endif %},
"can_manage_group": {% if user.admin_permissions.can_manage_group %} true {% else %} false {% endif %},
"can_view_user_log": {% if user.admin_permissions.can_view_user_log %} true {% else %} false {% endif %},
"can_view_admin_log": {% if user.admin_permissions.can_view_admin_log %} true {% else %} false {% endif %}
}
}
};
</script>
{% render_bundle 'sysAdmin' %}
{% endblock %}

View File

@ -130,6 +130,7 @@ from seahub.api2.endpoints.admin.address_book.groups import AdminAddressBookGrou
AdminAddressBookGroup
from seahub.api2.endpoints.admin.group_owned_libraries import AdminGroupOwnedLibraries, \
AdminGroupOwnedLibrary
from seahub.api2.endpoints.admin.file_scan_records import AdminFileScanRecords
urlpatterns = [
url(r'^accounts/', include('seahub.base.registration_urls')),
@ -501,6 +502,9 @@ urlpatterns = [
url(r'^api/v2.1/admin/address-book/groups/$', AdminAddressBookGroups.as_view(), name='api-v2.1-admin-address-book-groups'),
url(r'^api/v2.1/admin/address-book/groups/(?P<group_id>\d+)/$', AdminAddressBookGroup.as_view(), name='api-v2.1-admin-address-book-group'),
## admin::file-scan-records
url(r'^api/v2.1/admin/file-scan-records/$', AdminFileScanRecords.as_view(), name='api-v2.1-admin-file-scan-records'),
### system admin ###
url(r'^sysadmin/$', sysadmin, name='sysadmin'),
url(r'^sys/settings/$', sys_settings, name='sys_settings'),
@ -572,6 +576,15 @@ urlpatterns = [
url(r'^client-login/$', client_token_login, name='client_token_login'),
]
try:
from seahub.settings import ENABLE_FILE_SCAN
except ImportError:
ENABLE_FILE_SCAN = False
if ENABLE_FILE_SCAN:
urlpatterns += [
url(r'^sys/file-scan-records/$', sys_file_scan_records, name="sys_file_scan_records"),
]
from seahub.utils import EVENTS_ENABLED
if EVENTS_ENABLED:
urlpatterns += [

View File

@ -829,6 +829,11 @@ if EVENTS_CONFIG_FILE:
def get_virus_record_by_id(vid):
with _get_seafevents_session() as session:
return seafevents.get_virus_record_by_id(session, vid)
def get_file_scan_record(start=-1, limit=-1):
records = seafevents_api.get_content_scan_results(start, limit)
return records if records else []
else:
EVENTS_ENABLED = False
def get_user_events():
@ -867,6 +872,8 @@ else:
pass
def get_virus_record_by_id(vid):
pass
def get_file_scan_record():
pass
def calc_file_path_hash(path, bits=12):
if isinstance(path, unicode):

View File

@ -88,8 +88,16 @@ try:
from seahub_extra.organizations.models import OrgSettings
except ImportError:
MULTI_TENANCY = False
try:
from seahub.settings import ENABLE_SYSADMIN_EXTRA
except ImportError:
ENABLE_SYSADMIN_EXTRA = False
from seahub.utils.two_factor_auth import has_two_factor_auth
from termsandconditions.models import TermsAndConditions
try:
from seahub.settings import ENABLE_FILE_SCAN
except ImportError:
ENABLE_FILE_SCAN = False
logger = logging.getLogger(__name__)
@ -124,6 +132,22 @@ def sysadmin(request):
'trash_repos_expire_days': expire_days if expire_days > 0 else 30,
})
@login_required
@sys_staff_required
def sys_file_scan_records(request):
return render(request, 'sysadmin/sys_file_scan_records_react.html', {
'constance_enabled': dj_settings.CONSTANCE_ENABLED,
'multi_tenancy': MULTI_TENANCY,
'multi_institution': getattr(dj_settings, 'MULTI_INSTITUTION', False),
'sysadmin_extra_enabled': ENABLE_SYSADMIN_EXTRA,
'enable_guest_invitation': ENABLE_GUEST_INVITATION,
'enable_terms_and_conditions': config.ENABLE_TERMS_AND_CONDITIONS,
'enable_file_scan': ENABLE_FILE_SCAN,
})
@login_required
@sys_staff_required
def sys_statistic_file(request):