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:
parent
53c3791043
commit
8c81489c51
@ -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: {
|
||||
|
@ -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: {
|
||||
|
@ -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;
|
||||
|
137
frontend/src/pages/sys-admin/file-scan-records.js
Normal file
137
frontend/src/pages/sys-admin/file-scan-records.js
Normal 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;
|
60
frontend/src/pages/sys-admin/index.js
Normal file
60
frontend/src/pages/sys-admin/index.js
Normal 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')
|
||||
);
|
31
frontend/src/pages/sys-admin/main-panel.js
Normal file
31
frontend/src/pages/sys-admin/main-panel.js
Normal 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;
|
183
frontend/src/pages/sys-admin/side-panel.js
Normal file
183
frontend/src/pages/sys-admin/side-panel.js
Normal 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;
|
@ -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 : '';
|
||||
|
@ -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";}
|
||||
|
64
seahub/api2/endpoints/admin/file_scan_records.py
Normal file
64
seahub/api2/endpoints/admin/file_scan_records.py
Normal 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)
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
33
seahub/templates/sysadmin/sys_file_scan_records_react.html
Normal file
33
seahub/templates/sysadmin/sys_file_scan_records_react.html
Normal 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 %}
|
@ -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 += [
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user