1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 23:20:51 +00:00

User perm check (#2876)

* added 'user permission check'

* added 'can add repo' check

* [dir view, repo wiki mode] added condition check for 'share current dir'

* [dir view, repo wiki mode] modified var name
This commit is contained in:
llj
2019-01-24 10:02:18 +08:00
committed by Daniel Pan
parent 123a442319
commit 6e99897335
12 changed files with 96 additions and 27 deletions

View File

@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Router, navigate } from '@reach/router';
import { siteRoot } from './utils/constants';
import { siteRoot, canAddRepo } from './utils/constants';
import { Utils } from './utils/utils';
import SidePanel from './components/side-panel';
import MainPanel from './components/main-panel';
@@ -176,12 +176,17 @@ class App extends Component {
render() {
let { currentTab } = this.state;
const home = canAddRepo ?
<MyLibraries path={ siteRoot } onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> :
<SharedLibrariesWrapper path={ siteRoot } onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />;
return (
<div id="main">
<SidePanel isSidePanelClosed={this.state.isSidePanelClosed} onCloseSidePanel={this.onCloseSidePanel} currentTab={currentTab} tabItemClick={this.tabItemClick} draftCounts={this.state.draftCounts} />
<MainPanel>
<Router>
<MyLibraries path={ siteRoot } onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
{home}
<FilesActivitiesWrapper path={siteRoot + 'dashboard'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
<DraftsViewWrapper path={siteRoot + 'drafts'}
currentTab={currentTab}

View File

@@ -21,6 +21,8 @@ const propTypes = {
errorMsg: PropTypes.string.isRequired,
repoID: PropTypes.string.isRequired,
repoName: PropTypes.string.isRequired,
repoEncrypted: PropTypes.bool.isRequired,
showShareBtn: PropTypes.bool.isRequired,
pathExist: PropTypes.bool.isRequired,
permission: PropTypes.bool.isRequired,
isDirentListLoading: PropTypes.bool.isRequired,
@@ -154,6 +156,7 @@ class DirPanel extends React.Component {
isViewFile={false}
path={this.props.path}
repoID={this.props.repoID}
showShareBtn={this.props.showShareBtn}
onAddFile={this.props.onAddFile}
onAddFolder={this.props.onAddFolder}
onUploadFile={this.onUploadFile}

View File

@@ -1,7 +1,7 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { siteRoot } from '../../utils/constants';
import { siteRoot, canGenerateShareLink, canGenerateUploadLink, username } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import { gettext } from '../../utils/constants';
@@ -27,9 +27,14 @@ class DirView extends React.Component {
this.state = {
path: '/',
pathExist: true,
repoName: '',
repoID: '',
repoEncrypted: false,
isAdmin: false,
ownerEmail: '',
userPerm: '',
permission: true,
libNeedDecrypt: false,
isDirentSelected: false,
@@ -86,6 +91,8 @@ class DirView extends React.Component {
repoID: repoInfo.repo_id,
repoName: repoInfo.repo_name,
repoEncrypted: repoInfo.encrypted,
isAdmin: repoInfo.is_admin,
ownerEmail: repoInfo.owner_email,
permission: repoInfo.permission === 'rw',
libNeedDecrypt: res.data.lib_need_decrypt,
});
@@ -181,6 +188,7 @@ class DirView extends React.Component {
this.setState({
isDirentListLoading: false,
pathExist: true,
userPerm: res.data.user_perm,
direntList: Utils.sortDirents(direntList, this.state.sortBy, this.state.sortOrder),
dirID: res.headers.oid,
});
@@ -661,6 +669,16 @@ class DirView extends React.Component {
}
render() {
let showShareBtn = false;
const { repoEncrypted, isAdmin, ownerEmail, userPerm } = this.state;
const isRepoOwner = ownerEmail == username;
if (!repoEncrypted && (
canGenerateShareLink || canGenerateUploadLink ||
isRepoOwner || isAdmin) && (
userPerm == 'rw' || userPerm == 'r')) {
showShareBtn = true;
}
return (
<DirPanel
pathPrefix={this.props.pathPrefix}
@@ -675,6 +693,7 @@ class DirView extends React.Component {
isDirentListLoading={this.state.isDirentListLoading}
isDirentSelected={this.state.isDirentSelected}
isAllDirentSelected={this.state.isAllDirentSelected}
showShareBtn={showShareBtn}
direntList={this.state.direntList}
sortBy={this.state.sortBy}
sortOrder={this.state.sortOrder}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Link } from '@reach/router';
import Group from '../models/group';
import { gettext, siteRoot, enableWiki } from '../utils/constants';
import { gettext, siteRoot, enableWiki, canAddRepo, canGenerateShareLink, canGenerateUploadLink } from '../utils/constants';
import { seafileAPI } from '../utils/seafile-api';
import { Badge } from 'reactstrap';
@@ -101,26 +101,44 @@ class MainSideNav extends React.Component {
height = this.adminHeight;
}
let style = {height: height};
let linksNavItem = null;
if (canGenerateShareLink) {
linksNavItem = (
<li className="nav-item">
<Link to={siteRoot + 'share-admin-share-links/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-share-links')}`} title={gettext('Links')} onClick={() => this.tabItemClick('share-admin-share-links')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Links')}</span>
</Link>
</li>
);
} else if (canGenerateUploadLink) {
linksNavItem = (
<li className="nav-item">
<Link to={siteRoot + 'share-admin-upload-links/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-upload-links')}`} title={gettext('Links')} onClick={() => this.tabItemClick('share-admin-upload-links')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Links')}</span>
</Link>
</li>
);
}
return (
<ul className={`nav sub-nav nav-pills flex-column ${this.state.sharedExtended ? 'side-panel-slide' : 'side-panel-slide-up'}`} style={style} >
{canAddRepo && (
<li className="nav-item">
<Link to={siteRoot + 'share-admin-libs/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-libs')}`} title={gettext('Libraries')} onClick={() => this.tabItemClick('share-admin-libs')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Libraries')}</span>
</Link>
</li>
)}
<li className="nav-item">
<Link to={siteRoot + 'share-admin-folders/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-folders')}`} title={gettext('Folders')} onClick={() => this.tabItemClick('share-admin-folders')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Folders')}</span>
</Link>
</li>
<li className="nav-item">
<Link to={siteRoot + 'share-admin-share-links/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-share-links') || this.getActiveClass('share-admin-upload-links')}`} title={gettext('Links')} onClick={() => this.tabItemClick('share-admin-share-links')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Links')}</span>
</Link>
</li>
{linksNavItem}
</ul>
);
}
@@ -131,12 +149,14 @@ class MainSideNav extends React.Component {
<div className="side-nav-con">
<h3 className="sf-heading">{gettext('Files')}</h3>
<ul className="nav nav-pills flex-column nav-container">
{canAddRepo && (
<li className="nav-item">
<Link to={ siteRoot + 'my-libs/' } className={`nav-link ellipsis ${this.getActiveClass('my-libs') || this.getActiveClass('deleted') }`} title={gettext('My Libraries')} onClick={() => this.tabItemClick('my-libs')}>
<span className="sf2-icon-user" aria-hidden="true"></span>
<span className="nav-text">{gettext('My Libraries')}</span>
</Link>
</li>
)}
<li className="nav-item">
<Link to={siteRoot + 'shared-libs/'} className={`nav-link ellipsis ${this.getActiveClass('shared-libs')}`} title={gettext('Shared with me')} onClick={() => this.tabItemClick('shared-libs')}>
<span className="sf2-icon-share" aria-hidden="true"></span>

View File

@@ -13,6 +13,7 @@ const propTypes = {
permission: PropTypes.string, //just for view file and premission is file permission
path: PropTypes.string.isRequired,
repoID: PropTypes.string.isRequired,
showShareBtn: PropTypes.bool.isRequired,
onAddFile: PropTypes.func.isRequired,
onAddFolder: PropTypes.func.isRequired,
onUploadFile: PropTypes.func.isRequired,
@@ -192,7 +193,9 @@ class DirOperationToolbar extends React.Component {
<button className="btn btn-secondary operation-item" title={gettext('New')} onClick={this.onCreateClick}>{gettext('New')}</button>
</Fragment>
)}
{this.props.showShareBtn &&
<button className="btn btn-secondary operation-item" title={gettext('Share')} onClick={this.onShareClick}>{gettext('Share')}</button>
}
</div>
{this.state.isUploadMenuShow && (
<ul className="menu dropdown-menu" style={this.state.operationMenuStyle}>

View File

@@ -1,7 +1,7 @@
import React,{ Fragment } from 'react';
import { Popover } from 'reactstrap';
import PropTypes from 'prop-types';
import { gettext, siteRoot, username, loginUrl } from '../../utils/constants';
import { gettext, siteRoot, username, loginUrl, canAddRepo } from '../../utils/constants';
import { Link } from '@reach/router';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
@@ -331,9 +331,11 @@ class GroupView extends React.Component {
<div className="cur-view-toolbar border-left-show">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
<div className="operation">
{canAddRepo && (
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateRepoToggle}>
<i className="fas fa-plus-square text-secondary mr-1"></i>{gettext('New Library')}
</button>
)}
</div>
</div>
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />

View File

@@ -1,10 +1,9 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { Link } from '@reach/router';
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
import { gettext, siteRoot, storages, canGenerateShareLink, canGenerateUploadLink, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants';
import { gettext, siteRoot, storages, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api';
import RenameInput from '../../components/rename-input';
@@ -144,9 +143,6 @@ class Item extends Component {
changePassword = () => {
}
showLinks = () => {
}
folderPerm = () => {
}
@@ -194,8 +190,6 @@ class Item extends Component {
operationMenuToggleIconClassName += iconVisibility;
}
// const showShareLinks = !data.encrypted && (canGenerateShareLink || canGenerateUploadLink);
const commonToggle = (
<DropdownToggle
tag="i"
@@ -212,7 +206,6 @@ class Item extends Component {
<DropdownItem onClick={this.transfer}>{gettext('Transfer')}</DropdownItem>
<DropdownItem onClick={this.historySetting}>{gettext('History Setting')}</DropdownItem>
{data.encrypted ? <DropdownItem onClick={this.changePassword}>{gettext('Change Password')}</DropdownItem> : ''}
{/* {showShareLinks ? <DropdownItem onClick={this.showLinks}>{gettext('Share Links')}</DropdownItem> : ''} */}
{folderPermEnabled ? <DropdownItem onClick={this.folderPerm}>{gettext('Folder Permission')}</DropdownItem> : ''}
<DropdownItem onClick={this.showDetails}>{gettext('Details')}</DropdownItem>
</React.Fragment>

View File

@@ -24,6 +24,7 @@ const propTypes = {
hash: PropTypes.string,
path: PropTypes.string.isRequired,
repoEncrypted: PropTypes.bool.isRequired,
showShareBtn: PropTypes.bool.isRequired,
// whether the file or dir corresponding to the path exist
pathExist: PropTypes.bool.isRequired,
isFileLoading: PropTypes.bool.isRequired,
@@ -188,6 +189,7 @@ class MainPanel extends Component {
hasDraft={this.props.hasDraft}
permission={this.props.permission}
isViewFile={this.props.isViewFile}
showShareBtn={this.props.showShareBtn}
onAddFile={this.props.onAddFile}
onAddFolder={this.props.onAddFolder}
onUploadFile={this.onUploadFile}

View File

@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import moment from 'moment';
import { gettext, repoID, siteRoot, initialPath, isDir, slug } from './utils/constants';
import { gettext, repoID, siteRoot, initialPath, isDir, slug , canGenerateShareLink, canGenerateUploadLink, username } from './utils/constants';
import { seafileAPI } from './utils/seafile-api';
import { Utils } from './utils/utils';
import collabServer from './utils/collab-server';
@@ -15,6 +15,8 @@ import ModalPortal from './components/modal-portal';
import Dirent from './models/dirent';
import FileTag from './models/file-tag';
import RepoTag from './models/repo-tag';
import RepoInfo from './models/repo-info';
import './assets/css/fa-solid.css';
import './assets/css/fa-regular.css';
import './assets/css/fontawesome.css';
@@ -29,6 +31,10 @@ class Wiki extends Component {
super(props);
this.state = {
repoEncrypted: false,
isAdmin: false,
ownerEmail: '',
userPerm: '',
path: '',
pathExist: true,
treeData: treeHelper.buildTree(),
@@ -74,9 +80,12 @@ class Wiki extends Component {
componentDidMount() {
seafileAPI.getRepoInfo(repoID).then(res => {
let repoInfo = new RepoInfo(res.data);
this.setState({
libNeedDecrypt: res.data.lib_need_decrypt,
repoEncrypted: res.data.encrypted
repoEncrypted: repoInfo.encrypted,
isAdmin: repoInfo.is_admin,
ownerEmail: repoInfo.owner_email
});
if (!res.data.lib_need_decrypt) {
@@ -236,6 +245,7 @@ class Wiki extends Component {
});
this.setState({
userPerm: res.data.user_perm,
direntList: Utils.sortDirents(direntList, this.state.sortBy, this.state.sortOrder),
isDirentListLoading: false,
dirID: res.headers.oid,
@@ -1001,6 +1011,16 @@ class Wiki extends Component {
)
}
let showShareBtn = false;
const { repoEncrypted, isAdmin, ownerEmail, userPerm } = this.state;
const isRepoOwner = ownerEmail == username;
if (!repoEncrypted && (
canGenerateShareLink || canGenerateUploadLink ||
isRepoOwner || isAdmin) && (
userPerm == 'rw' || userPerm == 'r')) {
showShareBtn = true;
}
return (
<div id="main" className="wiki-main">
<SidePanel
@@ -1029,6 +1049,7 @@ class Wiki extends Component {
content={this.state.content}
lastModified={this.state.lastModified}
latestContributor={this.state.latestContributor}
showShareBtn={showShareBtn}
direntList={this.state.direntList}
sortBy={this.state.sortBy}
sortOrder={this.state.sortOrder}

View File

@@ -19,8 +19,9 @@ export const seafileCollabServer = window.app.pageOptions.seafileCollabServer;
export const name = window.app.pageOptions.name;
export const contactEmail = window.app.pageOptions.contactEmail;
export const username = window.app.pageOptions.username;
export const canGenerateShareLink = window.app.pageOptions.canGenerateShareLink === 'True';
export const canGenerateUploadLink = window.app.pageOptions.canGenerateUploadLink === 'True';
export const canAddRepo = window.app.pageOptions.canAddRepo;
export const canGenerateShareLink = window.app.pageOptions.canGenerateShareLink;
export const canGenerateUploadLink = window.app.pageOptions.canGenerateUploadLink;
export const canViewOrg = window.app.pageOptions.canViewOrg === 'True';
export const fileAuditEnabled = window.app.pageOptions.fileAuditEnabled ? true : false;
export const enableFileComment = window.app.pageOptions.enableFileComment ? true : false;

View File

@@ -42,8 +42,9 @@
name: "{{request.user.username|email2nickname|escapejs}}",
contactEmail: "{{request.user.username|email2contact_email|escapejs}}",
username: "{{request.user.username|escapejs}}",
canGenerateShareLink: '{{ user.permissions.can_generate_share_link }}',
canGenerateUploadLink: '{{ user.permissions.can_generate_upload_link }}',
canAddRepo: {% if user.permissions.can_add_repo %} true {% else %} false {% endif %},
canGenerateShareLink: {% if user.permissions.can_generate_share_link %} true {% else %} false {% endif %},
canGenerateUploadLink: {% if user.permissions.can_generate_upload_link %} true {% else %} false {% endif %},
canViewOrg:'{{ user.permissions.can_view_org }}',
fileAuditEnabled: '{{ file_audit_enabled }}',
enableFileComment: '{{ enable_file_comment }}',
@@ -66,7 +67,7 @@
shareLinkExpireDaysMin: "{{ share_link_expire_days_min }}",
shareLinkExpireDaysMax: "{{ share_link_expire_days_max }}",
maxFileName: "{{ max_file_name }}",
enableWiki: {% if enable_wiki %} true {% else %} false {% endif %},
enableWiki: {% if user.permissions.can_use_wiki %} true {% else %} false {% endif %},
enableEncryptedLibrary: '{{ enable_encrypted_library }}',
enableRepoHistorySetting: '{{ enable_repo_history_setting }}',
isSystemStaff: {% if request.user.is_staff %} true {% else %} false {% endif %},

View File

@@ -1220,7 +1220,6 @@ def react_fake_view(request, **kwargs):
return render(request, "react_app.html", {
'seafile_collab_server': SEAFILE_COLLAB_SERVER,
'storages': get_library_storages(request),
'enable_wiki': request.user.permissions.can_use_wiki(),
'enable_repo_snapshot_label': settings.ENABLE_REPO_SNAPSHOT_LABEL,
'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN,
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,