1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-02 07:27:04 +00:00

corrent logic for check generate share link, and share link permissions (#4121)

This commit is contained in:
Leo
2019-10-12 14:54:25 +08:00
committed by Daniel Pan
parent 821d6afbaa
commit 5b789c4300
9 changed files with 140 additions and 65 deletions

View File

@@ -25,11 +25,6 @@ class GenerateShareLink extends React.Component {
this.isExpireDaysNoLimit = (parseInt(shareLinkExpireDaysMin) === 0 && parseInt(shareLinkExpireDaysMax) === 0 && shareLinkExpireDaysDefault == 0);
this.defaultExpireDays = this.isExpireDaysNoLimit ? '' : shareLinkExpireDaysDefault;
if (isPro) {
this.editOption = 'edit_download';
this.permissionOptions = ['preview_download', 'preview_only'];
}
this.state = {
isValidate: false,
isShowPasswordInput: false,
@@ -42,7 +37,8 @@ class GenerateShareLink extends React.Component {
sharedLinkInfo: null,
isNoticeMessageShow: false,
isLoading: true,
currentPermission: isPro ? this.permissionOptions[0] : '',
permissionOptions: [],
currentPermission: '',
isSendLinkShown: false
};
}
@@ -65,17 +61,34 @@ class GenerateShareLink extends React.Component {
toaster.danger(errMessage);
});
if (isPro && Utils.isEditableOfficeFile(path)) {
seafileAPI.getFileInfo(repoID, path).then((res) => {
if (res.data.can_edit) {
this.permissionOptions.push(this.editOption);
if (isPro) {
if (this.props.itemType === 'library') {
let permissionOptions = Utils.getShareLinkPermissionList(this.props.itemType, '', path);
this.setState({
permissionOptions: permissionOptions,
currentPermission: permissionOptions[0],
});
} else {
let getDirentInfoAPI;
if (this.props.itemType === 'file') {
getDirentInfoAPI = seafileAPI.getFileInfo(repoID, path);
} else if (this.props.itemType === 'dir') {
getDirentInfoAPI = seafileAPI.getDirInfo(repoID, path);
}
getDirentInfoAPI.then((res) => {
let permission = res.data.permission;
let permissionOptions = Utils.getShareLinkPermissionList(this.props.itemType, permission, path);
this.setState({
permissionOptions: permissionOptions,
currentPermission: permissionOptions[0],
});
}).catch(error => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
}
}
onPasswordInputChecked = () => {
this.setState({
@@ -260,7 +273,6 @@ class GenerateShareLink extends React.Component {
}
render() {
if (this.state.isLoading) {
return <Loading />;
}
@@ -394,7 +406,7 @@ class GenerateShareLink extends React.Component {
<span>{gettext('Set permission')}</span>
</Label>
</FormGroup>
{this.permissionOptions.map((item, index) => {
{this.state.permissionOptions.map((item, index) => {
return (
<FormGroup check className="permission" key={index}>
<Label className="form-check-label">

View File

@@ -129,6 +129,7 @@ class ShareDialog extends React.Component {
itemPath={this.props.itemPath}
repoID={this.props.repoID}
closeShareDialog={this.props.toggleDialog}
itemType={itemType}
/>
</TabPane>
}
@@ -166,6 +167,7 @@ class ShareDialog extends React.Component {
renderFileContent = () => {
let activeTab = this.state.activeTab;
const { itemType } = this.props;
return (
<Fragment>
@@ -190,6 +192,7 @@ class ShareDialog extends React.Component {
itemPath={this.props.itemPath}
repoID={this.props.repoID}
closeShareDialog={this.props.toggleDialog}
itemType={itemType}
/>
</TabPane>
{activeTab === 'internalLink' &&

View File

@@ -494,11 +494,13 @@ class DirentListItem extends React.Component {
}
renderItemOperation = () => {
let { dirent, selectedDirentList, currentRepoInfo } = this.props;
if (currentRepoInfo.permission === 'cloud-edit' || currentRepoInfo.permission === 'preview') {
return '';
}
let showShareBtn = Utils.isHasPermissionToShare(currentRepoInfo, dirent.permission, dirent);
let { dirent, selectedDirentList } = this.props;
// no need to check whether show shareBtn or not.
// according to specification below, shareBtn aways show.
// check for "generate uploadlink" or other tabs should put inside the shareDialog.
// https://dev.seafile.com/seahub/lib/d6f300e7-bb2b-4722-b83e-cf45e370bfbc/file/seaf-server%20%E5%8A%9F%E8%83%BD%E8%AE%BE%E8%AE%A1/%E6%9D%83%E9%99%90%E7%9B%B8%E5%85%B3/%E8%B5%84%E6%96%99%E5%BA%93%E6%9D%83%E9%99%90%E8%A7%84%E8%8C%83.md
// let showShareBtn = Utils.isHasPermissionToShare(currentRepoInfo, dirent.permission, dirent);
return (
<Fragment>
@@ -512,11 +514,9 @@ class DirentListItem extends React.Component {
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
</li>
)}
{showShareBtn && (
<li className="operation-group-item">
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
</li>
)}
{dirent.permission === 'rw' && (
<li className="operation-group-item">
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
@@ -546,7 +546,7 @@ class DirentListItem extends React.Component {
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
</li>
)}
{showShareBtn && (
{(
<li className="operation-group-item">
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
</li>

View File

@@ -46,6 +46,10 @@ class SelectEditor extends React.Component {
});
}
componentWillReceiveProps() {
this.setOptions();
}
componentWillUnmount() {
document.removeEventListener('click', this.onHideSelect);
}

View File

@@ -91,56 +91,60 @@ class Item extends Component {
constructor(props) {
super(props);
const item = this.props.item;
if (isPro) {
this.editOption = 'edit_download';
this.permissionOptions = ['preview_download', 'preview_only'];
this.updatePermissionOptions();
}
this.state = {
currentPermission: isPro ? this.getCurrentPermission() : '',
isOpIconShown: false,
isOpMenuOpen: false, // for mobile
isPermSelectDialogOpen: false, // for mobile
isLinkDialogOpen: false
isLinkDialogOpen: false,
permissionOptions: [],
currentPermission: '',
};
}
componentDidMount() {
if (isPro) {
this.updatePermissionOptions();
}
}
updatePermissionOptions = () => {
const item = this.props.item;
let options = this.permissionOptions;
if (!Utils.isEditableOfficeFile(item.obj_name)) {
return ;
}
if (item.permissions.can_edit) {
options.push(this.editOption);
return ;
}
seafileAPI.getFileInfo(item.repo_id, item.path).then((res) => {
if (res.data.can_edit) {
options.push(this.editOption);
return ;
}
if (item.is_dir && item.path === '/') {
let permissionOptions = Utils.getShareLinkPermissionList('library', '', item.path);
this.setState({
permissionOptions: permissionOptions,
});
} else {
let { repo_id, path } = item;
let getDirentInfoAPI = item.is_dir ? seafileAPI.getDirInfo(repo_id, path) : seafileAPI.getFileInfo(repo_id, path);
getDirentInfoAPI.then((res) => {
let itemType = item.is_dir ? 'dir' : 'file';
let permission = res.data.permission;
let permissionOptions = Utils.getShareLinkPermissionList(itemType, permission, item.path);
this.setState({
permissionOptions: permissionOptions,
});
}).catch(error => {
return ;
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
}
this.setState({
currentPermission: this.getCurrentPermission(),
});
}
getCurrentPermission = () => {
const options = this.permissionOptions;
const { can_edit, can_download } = this.props.item.permissions;
switch (`${can_edit} ${can_download}`) {
case 'false true':
return options[0];
return 'preview_download';
case 'false false':
return options[1];
return 'preview_only';
case 'true true':
return this.editOption;
return 'edit_download';
case 'true false':
return 'cloud_edit';
}
}
@@ -214,7 +218,7 @@ class Item extends Component {
render() {
const item = this.props.item;
const { currentPermission, isOpIconShown, isPermSelectDialogOpen, isLinkDialogOpen } = this.state;
const { currentPermission, permissionOptions , isOpIconShown, isPermSelectDialogOpen, isLinkDialogOpen } = this.state;
let iconUrl, objUrl;
if (item.is_dir) {
@@ -242,7 +246,7 @@ class Item extends Component {
isTextMode={true}
isEditIconShow={isOpIconShown && !item.is_expired}
currentPermission={currentPermission}
permissionOptions={this.permissionOptions}
permissionOptions={permissionOptions}
onPermissionChanged={this.changePerm}
/>
</td>
@@ -294,7 +298,7 @@ class Item extends Component {
{isPermSelectDialogOpen &&
<ShareLinkPermissionSelect
currentPerm={currentPermission}
permissions={this.permissionOptions}
permissions={permissionOptions}
changePerm={this.changePerm}
toggleDialog={this.togglePermSelectDialog}
/>

View File

@@ -109,6 +109,39 @@ export const Utils = {
}
},
getShareLinkPermissionList: function(itemType, permission, path) {
// itemType: library, dir, file
// permission: rw, r, admin, cloud-edit, preview
// if item is library, can preview and download, no need to check
// if item is dir, check can download
// if item is file, check can download and check can edit
let editDownloadOption = 'edit_download';
let editOnly = 'cloud_edit';
let downloadOption = 'preview_download';
let permissionOptions = ['preview_only'];
if (itemType === 'library') {
permissionOptions.push(downloadOption);
} else if (itemType === 'dir') {
if (permission == 'rw' || permission == 'admin' || permission == 'r') {
permissionOptions.push(downloadOption);
}
} else if (itemType === 'file') {
if (permission == 'rw' || permission == 'admin' || permission == 'r') {
permissionOptions.push(downloadOption);
}
if (this.isEditableOfficeFile(path) && (permission == 'rw' || permission == 'admin')) {
permissionOptions.push(editDownloadOption);
}
if (this.isEditableOfficeFile(path) && (permission == 'cloud-edit')) {
permissionOptions.push(editOnly);
}
}
return permissionOptions;
},
isEditableOfficeFile: function(filename) {
// no file ext
if (filename.lastIndexOf('.') == -1) {
@@ -562,7 +595,19 @@ export const Utils = {
"can_download": true
}
};
case 'cloud_edit':
return {
value: permission,
text: gettext('Edit on cloud'),
permissionDetails: {
'can_edit': true,
"can_download": false
}
};
}
return {
text: '',
};
},
formatSize: function(options) {

View File

@@ -563,7 +563,8 @@ class DirDetailView(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if not check_folder_permission(request, repo_id, path):
permission = check_folder_permission(request, repo_id, path)
if not permission:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
@@ -579,6 +580,7 @@ class DirDetailView(APIView):
'path': path,
'name': dir_obj.obj_name,
'mtime': timestamp_to_isoformat_timestr(dir_obj.mtime),
'permission': permission,
}
return Response(dir_info)

View File

@@ -29,7 +29,6 @@ from seahub.utils import gen_shared_link, is_org_context, normalize_file_path, \
normalize_dir_path, is_pro_version, get_file_type_and_ext
from seahub.utils.file_op import if_locked_by_online_office
from seahub.utils.file_types import IMAGE, VIDEO, XMIND
from seahub.views import check_folder_permission
from seahub.utils.timeutils import datetime_to_isoformat_timestr, \
timestamp_to_isoformat_timestr
from seahub.utils.repo import parse_repo_perm
@@ -288,11 +287,12 @@ class ShareLinks(APIView):
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if parse_repo_perm(check_folder_permission(request, repo_id, path)).can_download is False:
username = request.user.username
permission_by_path = seafile_api.check_permission_by_path(repo_id, path, username)
if parse_repo_perm(permission_by_path).can_generate_share_link is False:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
username = request.user.username
org_id = request.user.org.org_id if is_org_context(request) else None
if s_type == 'f':
fs = FileShare.objects.get_file_link_by_path(username, repo_id, path)

View File

@@ -54,6 +54,7 @@ def parse_repo_perm(perm):
'can_edit_on_web', # edit files on web
'can_copy', # copy files/folders on web
'can_preview', # preview files on web
'can_generate_share_link', # generate share link
])
RP.can_download = True if perm in [
@@ -70,6 +71,10 @@ def parse_repo_perm(perm):
PERMISSION_READ, PERMISSION_READ_WRITE, PERMISSION_ADMIN,
PERMISSION_PREVIEW, PERMISSION_PREVIEW_EDIT
] else False
RP.can_generate_share_link = True if perm in [
PERMISSION_READ_WRITE, PERMISSION_READ, PERMISSION_ADMIN,
PERMISSION_PREVIEW, PERMISSION_PREVIEW_EDIT
] else False
return RP
def list_dir_by_path(cmmt, path):