mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 02:48:51 +00:00
custom share permission (#4967)
* custom share permission * remove path field * add permission manager ui * optimize custom permission manager style * add permission setting * add normalize_custom_permission_name * optimize repo custom permission * delete useless code * optimize code * optimize code * optimize markdown file page * fix a few bugs * add permission control * repair modify permission * optimize style * optimize copyright * add try-except * optimize code * move file&folder * batch operation item * repair batch move item * update copyright * optimize move permission control * optimize code * optimize code * optimize code & fix code wranning * optimize code * delete unsupport permission * optimize code * repair code bug * add pro limit * optimize code * add permission handle for permission editor * repair new file&folder bug * optimize file uploader code * custom permission user can not visit custom permission module * optimize code * forbid comment&detail module * optimize code * optimize modify/preview permission * optimize custom permission share perm * optimize view file module: file-toolbar * optimize custom drag move operation * repair column view bug * optimize drag operation code * repair code bug * optimize code Co-authored-by: shanshuirenjia <978987373@qq.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CustomPermissionEditor from './custom-permission-editor';
|
||||
|
||||
const propTypes = {
|
||||
onChangeMode: PropTypes.func.isRequired,
|
||||
addCustomPermission: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class AddCustomPermission extends React.Component {
|
||||
|
||||
onUpdateCustomPermission = (permission_name, permission_desc, permission) => {
|
||||
this.props.addCustomPermission(permission_name, permission_desc, permission)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<CustomPermissionEditor
|
||||
mode={'add'}
|
||||
onChangeMode={this.props.onChangeMode}
|
||||
onUpdateCustomPermission={this.onUpdateCustomPermission}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AddCustomPermission.propTypes = propTypes;
|
||||
|
||||
export default AddCustomPermission;
|
@@ -0,0 +1,208 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Alert, FormGroup, Input, Label, Tooltip } from 'reactstrap';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
import Loading from '../../loading';
|
||||
|
||||
const propTypes = {
|
||||
mode: PropTypes.string,
|
||||
permission: PropTypes.object,
|
||||
onChangeMode: PropTypes.func.isRequired,
|
||||
onUpdateCustomPermission: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class CustomPermissionEditor extends React.Component {
|
||||
|
||||
static defaultProps = {
|
||||
mode: 'add'
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
permission_name: '',
|
||||
permission_desc: '',
|
||||
permission: {
|
||||
upload: false,
|
||||
download: false,
|
||||
modify: false,
|
||||
copy: false,
|
||||
delete: false,
|
||||
preview: false,
|
||||
download_external_link: false,
|
||||
},
|
||||
errMessage: '',
|
||||
tooltipOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { permission } = this.props;
|
||||
if (permission) {
|
||||
this.setState({
|
||||
permission_name: permission.name,
|
||||
permission_desc: permission.description,
|
||||
permission: permission.permission,
|
||||
isLoading: false
|
||||
});
|
||||
} else {
|
||||
this.setState({isLoading: false});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onChangePermissionName = (evt) => {
|
||||
const { permission_name } = this.state;
|
||||
const newName = evt.target.value;
|
||||
if (newName === permission_name) return;
|
||||
this.setState({permission_name: newName});
|
||||
}
|
||||
|
||||
onChangePermissionDescription = (evt) => {
|
||||
const { permission_desc } = this.state;
|
||||
const newDescription = evt.target.value;
|
||||
if (newDescription === permission_desc) return;
|
||||
this.setState({permission_desc: newDescription});
|
||||
}
|
||||
|
||||
onChangePermission = (type) => {
|
||||
return () => {
|
||||
const { permission } = this.state;
|
||||
const value = !permission[type];
|
||||
const newPermission = Object.assign({}, permission, {[type]: value});
|
||||
this.setState({permission: newPermission});
|
||||
}
|
||||
}
|
||||
|
||||
validParams = () => {
|
||||
const { permission_name, permission_desc } = this.state;
|
||||
let isValid = false;
|
||||
let errMessage = '';
|
||||
if (!permission_name || !permission_name.trim()) {
|
||||
errMessage = gettext('Name is required');
|
||||
return { isValid, errMessage };
|
||||
}
|
||||
if (!permission_desc || !permission_desc.trim()) {
|
||||
errMessage = gettext('Description is required');
|
||||
return { isValid, errMessage };
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
return { isValid };
|
||||
}
|
||||
|
||||
onUpdateCustomPermission = () => {
|
||||
const { permission_name, permission_desc, permission } = this.state;
|
||||
const { isValid, errMessage } = this.validParams();
|
||||
if (!isValid) {
|
||||
this.setState({errMessage});
|
||||
return;
|
||||
}
|
||||
this.props.onUpdateCustomPermission(permission_name, permission_desc, permission);
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
this.setState({tooltipOpen: !this.state.tooltipOpen});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const { mode } = this.props;
|
||||
const title = mode === 'add' ? gettext('Add permission') : gettext('Edit permission');
|
||||
|
||||
const { isLoading, permission_name, permission_desc, permission, errMessage } = this.state;
|
||||
|
||||
return (
|
||||
<div className="custom-permission">
|
||||
<div className="permission-header">
|
||||
<div className="title">
|
||||
<div onClick={this.props.onChangeMode}>
|
||||
<i className="fa fa-arrow-left"></i>
|
||||
</div>
|
||||
<div>{title}</div>
|
||||
</div>
|
||||
<div className="operation">
|
||||
<button type="button" className="btn btn-outline-primary" onClick={this.onUpdateCustomPermission}>{gettext('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="permission-main mt-4">
|
||||
{isLoading && <Loading />}
|
||||
{!isLoading && (
|
||||
<Fragment>
|
||||
<div className="permission-name-desc d-flex">
|
||||
<FormGroup className="permission-name">
|
||||
<Label>{gettext('Permission name')}</Label>
|
||||
<Input value={permission_name || ''} onChange={this.onChangePermissionName} />
|
||||
</FormGroup>
|
||||
<FormGroup className="permission-desc">
|
||||
<Label>{gettext('Description')}</Label>
|
||||
<Input value={permission_desc || ''} onChange={this.onChangePermissionDescription} />
|
||||
</FormGroup>
|
||||
</div>
|
||||
{errMessage && <Alert color="danger">{errMessage}</Alert>}
|
||||
<div className="permission-options">
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('upload')} checked={permission.upload}/>
|
||||
<span>{gettext('Upload')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('download')} checked={permission.download}/>
|
||||
<span>{gettext('Download')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('modify')} checked={permission.modify}/>
|
||||
<span>{gettext('Modify')}</span>
|
||||
<span id="modify-tip" className="fa fa-question-circle ml-2" style={{color: '#999'}}></span>
|
||||
<Tooltip
|
||||
toggle={this.toggle}
|
||||
delay={{show: 0, hide: 0}}
|
||||
target={'modify-tip'}
|
||||
placement='bottom'
|
||||
isOpen={this.state.tooltipOpen}>
|
||||
({gettext('Modify includes modify file, create file and folder, move/rename file and folder')})
|
||||
</Tooltip>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('copy')} checked={permission.copy}/>
|
||||
<span>{gettext('Copy')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('delete')} checked={permission.delete}/>
|
||||
<span>{gettext('Delete')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('preview')} checked={permission.preview}/>
|
||||
<span>{gettext('Preview online')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.onChangePermission('download_external_link')} checked={permission.download_external_link}/>
|
||||
<span>{gettext('Generate share link')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
</div>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CustomPermissionEditor.propTypes = propTypes;
|
||||
|
||||
export default CustomPermissionEditor;
|
@@ -0,0 +1,67 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
permission: PropTypes.object.isRequired,
|
||||
onEditCustomPermission: PropTypes.func.isRequired,
|
||||
onDeleteCustomPermission: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class CustomPermissionItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isShowOperations: false
|
||||
};
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
this.setState({isShowOperations: true});
|
||||
}
|
||||
|
||||
onMouseOver = () => {
|
||||
this.setState({isShowOperations: true});
|
||||
}
|
||||
|
||||
onMouseLeave = () => {
|
||||
this.setState({isShowOperations: false});
|
||||
}
|
||||
|
||||
onEditCustomPermission = () => {
|
||||
const { permission } = this.props;
|
||||
this.props.onEditCustomPermission(permission)
|
||||
}
|
||||
|
||||
onDeleteCustomPermission = () => {
|
||||
const { permission } = this.props;
|
||||
this.props.onDeleteCustomPermission(permission)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { permission } = this.props;
|
||||
const { id, name, description } = permission;
|
||||
return (
|
||||
<tr key={id} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onMouseOver={this.onMouseOver}>
|
||||
<td width='22%' className="text-truncate" title={name}>{name}</td>
|
||||
<td width='56%' className="text-truncate">{description}</td>
|
||||
<td width='22%'>
|
||||
{this.state.isShowOperations && (
|
||||
<Fragment>
|
||||
<span className="permission-operation-btn edit" onClick={this.onEditCustomPermission}>
|
||||
<i className="fa fa-pencil-alt attr-action-icon"></i>
|
||||
</span>
|
||||
<span className="permission-operation-btn delete" onClick={this.onDeleteCustomPermission}>
|
||||
<i className="fa fa-trash attr-action-icon"></i>
|
||||
</span>
|
||||
</Fragment>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CustomPermissionItem.propTypes = propTypes;
|
||||
|
||||
export default CustomPermissionItem;
|
@@ -0,0 +1,159 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ListCustomPermission from './list-custom-permissions';
|
||||
import AddCustomPermission from './add-custom-permission';
|
||||
import EditCustomPermission from './edit-custom-permission';
|
||||
import Loading from '../../loading';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import toaster from '../../toast';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import CustomPermission from '../../../models/custom-permission';
|
||||
|
||||
const propTypes = {
|
||||
repoID: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
const MANAGER_STATE = {
|
||||
LIST: 'list',
|
||||
ADD: 'add',
|
||||
EDIT: 'edit',
|
||||
};
|
||||
|
||||
class CustomPermissionManager extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentMode: MANAGER_STATE.LIST,
|
||||
isLoading: true,
|
||||
permissions: [],
|
||||
currentPermission: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listCustomPermissions();
|
||||
}
|
||||
|
||||
listCustomPermissions = () => {
|
||||
const { repoID } = this.props;
|
||||
seafileAPI.listCustomPermissions(repoID).then(res => {
|
||||
const permissions = res.data.permission_list.map(item => new CustomPermission(item));
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
permissions: permissions
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
this.setState({isLoading: false});
|
||||
});
|
||||
}
|
||||
|
||||
addCustomPermission = (permission_name, permission_desc, permission) => {
|
||||
const { repoID } = this.props;
|
||||
seafileAPI.createCustomPermission(repoID, permission_name, permission_desc, permission).then(res => {
|
||||
const { permissions } = this.state;
|
||||
const customPermission = new CustomPermission(res.data.permission);
|
||||
permissions.unshift(customPermission)
|
||||
this.setState({
|
||||
permissions,
|
||||
currentMode: MANAGER_STATE.LIST
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
editCustomPermission = (newPermission) => {
|
||||
const { repoID } = this.props;
|
||||
seafileAPI.updateCustomPermission(repoID, newPermission).then(res => {
|
||||
const customPermission = new CustomPermission(res.data.permission);
|
||||
const { permissions } = this.state;
|
||||
const newPermissions = permissions.map(item => {
|
||||
if (item.id === customPermission.id) {
|
||||
return customPermission;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({
|
||||
permissions: newPermissions,
|
||||
currentMode: MANAGER_STATE.LIST
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
deleteCustomPermission = (permission) => {
|
||||
const { repoID } = this.props;
|
||||
const { id: permissionID } = permission;
|
||||
seafileAPI.deleteCustomPermission(repoID, permissionID).then(res => {
|
||||
const { permissions } = this.state;
|
||||
const newPermissions = permissions.filter(permission => permission.id !== permissionID);
|
||||
this.setState({permissions: newPermissions});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onChangeMode = () => {
|
||||
this.setState({currentMode: MANAGER_STATE.LIST});
|
||||
}
|
||||
|
||||
onAddCustomPermission = () => {
|
||||
this.setState({currentMode: MANAGER_STATE.ADD});
|
||||
}
|
||||
|
||||
onEditCustomPermission = (permission) => {
|
||||
this.setState({
|
||||
currentMode: MANAGER_STATE.EDIT,
|
||||
currentPermission: permission
|
||||
});
|
||||
}
|
||||
|
||||
onDeleteCustomPermission = (permission) => {
|
||||
this.deleteCustomPermission(permission);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.state.isLoading) {
|
||||
return <Loading />
|
||||
}
|
||||
|
||||
const { currentMode, permissions, currentPermission } = this.state;
|
||||
return (
|
||||
<div className="custom-permission-manager">
|
||||
{currentMode === MANAGER_STATE.LIST && (
|
||||
<ListCustomPermission
|
||||
permissions={permissions}
|
||||
onAddCustomPermission={this.onAddCustomPermission}
|
||||
onEditCustomPermission={this.onEditCustomPermission}
|
||||
onDeleteCustomPermission={this.onDeleteCustomPermission}
|
||||
/>
|
||||
)}
|
||||
{currentMode === MANAGER_STATE.ADD && (
|
||||
<AddCustomPermission
|
||||
onChangeMode={this.onChangeMode}
|
||||
addCustomPermission={this.addCustomPermission}
|
||||
/>
|
||||
)}
|
||||
{currentMode === MANAGER_STATE.EDIT && (
|
||||
<EditCustomPermission
|
||||
permission={currentPermission}
|
||||
onChangeMode={this.onChangeMode}
|
||||
editCustomPermission={this.editCustomPermission}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CustomPermissionManager.propTypes = propTypes;
|
||||
|
||||
export default CustomPermissionManager;
|
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CustomPermissionEditor from './custom-permission-editor';
|
||||
|
||||
const propTypes = {
|
||||
permission: PropTypes.object.isRequired,
|
||||
onChangeMode: PropTypes.func.isRequired,
|
||||
editCustomPermission: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
class EditCustomPermission extends React.Component {
|
||||
|
||||
onUpdateCustomPermission = (permission_name, permission_desc, permission) => {
|
||||
const { permission: editPermission } = this.props;
|
||||
const newPermission = Object.assign({}, editPermission, {
|
||||
name: permission_name,
|
||||
description: permission_desc,
|
||||
permission: permission
|
||||
});
|
||||
this.props.editCustomPermission(newPermission);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<CustomPermissionEditor
|
||||
mode={'edit'}
|
||||
permission={this.props.permission}
|
||||
onChangeMode={this.props.onChangeMode}
|
||||
onUpdateCustomPermission={this.onUpdateCustomPermission}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditCustomPermission.propTypes = propTypes;
|
||||
|
||||
export default EditCustomPermission;
|
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CustomPermissionItem from './custom-permission-item';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
permissions: PropTypes.array.isRequired,
|
||||
onAddCustomPermission: PropTypes.func.isRequired,
|
||||
onEditCustomPermission: PropTypes.func.isRequired,
|
||||
onDeleteCustomPermission: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class ListCustomPermissions extends React.Component {
|
||||
|
||||
render() {
|
||||
const { permissions } = this.props;
|
||||
|
||||
return (
|
||||
<div className="custom-permission">
|
||||
<div className="permission-header">
|
||||
<div className="title">{gettext('Permission')}</div>
|
||||
<div className="operation">
|
||||
<button type="button" className="btn btn-outline-primary" onClick={this.props.onAddCustomPermission}>{gettext('Add permission')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="permission-main mt-4">
|
||||
<table className="permissions-list-header">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='22%'>{gettext('Permission name')}</th>
|
||||
<th width='56%'>{gettext('Description')}</th>
|
||||
<th width='22%'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div className="permissions-list-body">
|
||||
<table>
|
||||
<tbody>
|
||||
{permissions.map(permission => {
|
||||
return (
|
||||
<CustomPermissionItem
|
||||
key={permission.id}
|
||||
permission={permission}
|
||||
onEditCustomPermission={this.props.onEditCustomPermission}
|
||||
onDeleteCustomPermission={this.props.onDeleteCustomPermission}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ListCustomPermissions.propTypes = propTypes;
|
||||
|
||||
export default ListCustomPermissions;
|
Reference in New Issue
Block a user