mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-02 07:47:32 +00:00
add wiki support owner department (#6113)
* add wiki support owner department * wiki can select owner --------- Co-authored-by: ‘JoinTyang’ <yangtong1009@163.com>
This commit is contained in:
parent
db4ed716aa
commit
c604bb2a94
@ -1,7 +1,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Input, Label } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
const propTypes = {
|
||||
toggleCancel: PropTypes.func.isRequired,
|
||||
@ -15,9 +19,35 @@ class AddWikiDialog extends React.Component {
|
||||
this.state = {
|
||||
name: '',
|
||||
isSubmitBtnActive: false,
|
||||
selectedOption: null,
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listDepartments();
|
||||
}
|
||||
|
||||
listDepartments = () => {
|
||||
seafileAPI.listDepartments().then(res => {
|
||||
const departments = res.data.sort((a, b) => {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
let options = [];
|
||||
for (let i = 0 ; i < departments.length; i++) {
|
||||
let obj = {};
|
||||
obj.value = departments[i].name;
|
||||
obj.id = departments[i].id;
|
||||
obj.label = departments[i].name;
|
||||
options.push(obj);
|
||||
}
|
||||
this.setState({options: options});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
inputNewName = (e) => {
|
||||
this.setState({
|
||||
name: e.target.value,
|
||||
@ -33,8 +63,9 @@ class AddWikiDialog extends React.Component {
|
||||
|
||||
handleSubmit = () => {
|
||||
const wikiName = this.state.name.trim();
|
||||
const departmentID = this.state.selectedOption ? this.state.selectedOption.id : null;
|
||||
if (!wikiName) return;
|
||||
this.props.addWiki(wikiName);
|
||||
this.props.addWiki(wikiName, departmentID);
|
||||
this.props.toggleCancel();
|
||||
};
|
||||
|
||||
@ -42,6 +73,10 @@ class AddWikiDialog extends React.Component {
|
||||
this.props.toggleCancel();
|
||||
};
|
||||
|
||||
handleSelectChange = (option) => {
|
||||
this.setState({ selectedOption: option });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isOpen={true} autoFocus={false} toggle={this.toggle}>
|
||||
@ -49,6 +84,18 @@ class AddWikiDialog extends React.Component {
|
||||
<ModalBody>
|
||||
<Label>{gettext('Name')}</Label>
|
||||
<Input onKeyDown={this.handleKeyDown} autoFocus={true} value={this.state.name} onChange={this.inputNewName}/>
|
||||
<Label className='mt-4'>{gettext('Wiki owner')} ({gettext('Optional')})</Label>
|
||||
<SeahubSelect
|
||||
onChange={this.handleSelectChange}
|
||||
options={this.state.options}
|
||||
hideSelectedOptions={true}
|
||||
placeholder={gettext('Select a department')}
|
||||
maxMenuHeight={200}
|
||||
value={this.state.selectedOption}
|
||||
components={{ NoOptionsMessage: (
|
||||
<div style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('No department')}</div>
|
||||
) }}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
|
@ -166,14 +166,11 @@ class TransferDialog extends React.Component {
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
|
||||
const { itemName: repoName } = this.props;
|
||||
let title = gettext('Transfer Library {library_name}');
|
||||
title = title.replace('{library_name}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
|
||||
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} style={{maxWidth: '720px'}} toggle={this.props.toggleDialog} className="transfer-dialog">
|
||||
<ModalHeader toggle={this.props.toggleDialog}>
|
||||
|
@ -80,8 +80,8 @@ class Wikis extends Component {
|
||||
this.setState({isShowAddDialog: !this.state.isShowAddDialog});
|
||||
};
|
||||
|
||||
addWiki = (wikiName) => {
|
||||
wikiAPI.addWiki2(wikiName).then((res) => {
|
||||
addWiki = (wikiName, departmentID) => {
|
||||
wikiAPI.addWiki2(wikiName, departmentID).then((res) => {
|
||||
let wikis = this.state.wikis.slice(0);
|
||||
let new_wiki = res.data;
|
||||
new_wiki['version'] = 'v2';
|
||||
|
@ -153,10 +153,13 @@ class WikiAPI {
|
||||
});
|
||||
}
|
||||
|
||||
addWiki2(wikiName) {
|
||||
addWiki2(wikiName, owner) {
|
||||
const url = this.server + '/api/v2.1/wikis2/';
|
||||
let form = new FormData();
|
||||
form.append('name', wikiName);
|
||||
if (owner) {
|
||||
form.append('owner', owner);
|
||||
}
|
||||
return this._sendPostRequest(url, form);
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,13 @@ from rest_framework import status
|
||||
import seaserv
|
||||
from seaserv import ccnet_api
|
||||
|
||||
from seahub.api2.utils import api_error
|
||||
from seahub.api2.utils import api_error, to_python_boolean
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.avatar.templatetags.group_avatar_tags import api_grp_avatar_url, get_default_group_avatar_url
|
||||
from seahub.utils import is_pro_version
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.group.utils import is_group_member
|
||||
from seahub.group.utils import is_group_member, is_group_admin
|
||||
from seahub.avatar.settings import GROUP_AVATAR_DEFAULT_SIZE
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -47,13 +47,24 @@ class Departments(APIView):
|
||||
except ValueError:
|
||||
avatar_size = GROUP_AVATAR_DEFAULT_SIZE
|
||||
|
||||
can_admin = request.GET.get('can_admin', 'false')
|
||||
|
||||
try:
|
||||
can_admin = to_python_boolean(can_admin)
|
||||
except:
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, 'can_admin invalid')
|
||||
|
||||
result = []
|
||||
for department in departments:
|
||||
department = seaserv.get_group(department.id)
|
||||
|
||||
username = request.user.username
|
||||
if not is_group_member(department.id, username):
|
||||
continue
|
||||
if can_admin:
|
||||
if not is_group_admin(department.id, username):
|
||||
continue
|
||||
else:
|
||||
if not is_group_member(department.id, username):
|
||||
continue
|
||||
|
||||
try:
|
||||
avatar_url, is_default, date_uploaded = api_grp_avatar_url(department.id, avatar_size)
|
||||
|
@ -23,7 +23,8 @@ from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.utils import api_error, to_python_boolean
|
||||
from seahub.wiki2.models import Wiki2 as Wiki
|
||||
from seahub.wiki2.utils import is_valid_wiki_name, can_edit_wiki, get_wiki_dirs_by_path, \
|
||||
get_wiki_config, WIKI_PAGES_DIR, WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME
|
||||
get_wiki_config, WIKI_PAGES_DIR, WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME, is_group_wiki, \
|
||||
check_wiki_admin_permission, check_wiki_permission
|
||||
from seahub.utils import is_org_context, get_user_repos, gen_inner_file_get_url, gen_file_upload_url, \
|
||||
normalize_dir_path, is_pro_version, check_filename_with_rename, is_valid_dirent_name
|
||||
from seahub.views import check_folder_permission
|
||||
@ -32,13 +33,17 @@ from seahub.base.templatetags.seahub_tags import email2nickname
|
||||
from seahub.utils.file_op import check_file_lock, ONLINE_OFFICE_LOCK_OWNER, if_locked_by_online_office
|
||||
from seahub.utils.repo import parse_repo_perm
|
||||
from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token
|
||||
from seahub.settings import SEADOC_SERVER_URL
|
||||
from seahub.settings import SEADOC_SERVER_URL, ENABLE_STORAGE_CLASSES, STORAGE_CLASS_MAPPING_POLICY, \
|
||||
ENCRYPTED_LIBRARY_VERSION
|
||||
from seahub.seadoc.sdoc_server_api import SdocServerAPI
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.tags.models import FileUUIDMap
|
||||
from seahub.seadoc.models import SeadocHistoryName, SeadocDraft, SeadocCommentReply
|
||||
from seahub.base.models import FileComment
|
||||
from seahub.api2.views import HTTP_447_TOO_MANY_FILES_IN_LIBRARY
|
||||
from seahub.group.utils import group_id_to_name, is_group_admin
|
||||
from seahub.utils.rpc import SeafileAPI
|
||||
from seahub.constants import PERMISSION_READ_WRITE
|
||||
|
||||
HTTP_520_OPERATION_FAILED = 520
|
||||
|
||||
@ -95,6 +100,10 @@ class Wikis2View(APIView):
|
||||
wiki_list = []
|
||||
for wiki in wikis:
|
||||
wiki_info = wiki.to_dict()
|
||||
if is_group_wiki(wiki):
|
||||
wiki_info['owner_nickname'] = group_id_to_name(wiki.owner)
|
||||
else:
|
||||
wiki_info['owner_nickname'] = email2nickname(wiki.owner)
|
||||
wiki_list.append(wiki_info)
|
||||
|
||||
return Response({'wikis': wiki_list})
|
||||
@ -115,18 +124,77 @@ class Wikis2View(APIView):
|
||||
msg = _('Name can only contain letters, numbers, blank, hyphen or underscore.')
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, msg)
|
||||
|
||||
wiki_owner = request.data.get('owner', 'me')
|
||||
|
||||
is_group_owner = False
|
||||
group_id = ''
|
||||
if wiki_owner == 'me':
|
||||
wiki_owner = request.user.username
|
||||
else:
|
||||
try:
|
||||
group_id = int(wiki_owner)
|
||||
except:
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, 'wiki_owner invalid')
|
||||
is_group_owner = True
|
||||
|
||||
org_id = -1
|
||||
if is_org_context(request):
|
||||
org_id = request.user.org.org_id
|
||||
|
||||
permission = PERMISSION_READ_WRITE
|
||||
if is_group_owner:
|
||||
group_id = int(group_id)
|
||||
# only group admin can create wiki
|
||||
if not is_group_admin(group_id, request.user.username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
group_quota = seafile_api.get_group_quota(group_id)
|
||||
group_quota = int(group_quota)
|
||||
if group_quota <= 0 and group_quota != -2:
|
||||
error_msg = 'No group quota.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# create group owned repo
|
||||
group_id = int(group_id)
|
||||
password = None
|
||||
if is_pro_version() and ENABLE_STORAGE_CLASSES:
|
||||
|
||||
if STORAGE_CLASS_MAPPING_POLICY in ('USER_SELECT', 'ROLE_BASED'):
|
||||
storage_id = None
|
||||
repo_id = seafile_api.add_group_owned_repo(group_id,
|
||||
wiki_name,
|
||||
permission,
|
||||
password,
|
||||
enc_version=ENCRYPTED_LIBRARY_VERSION,
|
||||
storage_id=storage_id)
|
||||
else:
|
||||
# STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING'
|
||||
repo_id = SeafileAPI.add_group_owned_repo(
|
||||
group_id, wiki_name, password, permission, org_id=org_id)
|
||||
else:
|
||||
repo_id = SeafileAPI.add_group_owned_repo(
|
||||
group_id, wiki_name, password, permission, org_id=org_id)
|
||||
else:
|
||||
if org_id and org_id > 0:
|
||||
repo_id = seafile_api.create_org_repo(wiki_name, '', username, org_id)
|
||||
else:
|
||||
repo_id = seafile_api.create_repo(wiki_name, '', username)
|
||||
|
||||
try:
|
||||
wiki = Wiki.objects.add(wiki_name=wiki_name, username=username, org_id=org_id)
|
||||
wiki = Wiki.objects.add(wiki_name=wiki_name, owner=wiki_owner, repo_id=repo_id)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg)
|
||||
|
||||
return Response(wiki.to_dict())
|
||||
wiki_info = wiki.to_dict()
|
||||
if not is_group_owner:
|
||||
wiki_info['owner_nickname'] = email2nickname(wiki.owner)
|
||||
else:
|
||||
wiki_info['owner_nickname'] = group_id_to_name(wiki.owner)
|
||||
|
||||
return Response(wiki_info)
|
||||
|
||||
|
||||
class Wiki2View(APIView):
|
||||
@ -143,23 +211,27 @@ class Wiki2View(APIView):
|
||||
except Wiki.DoesNotExist:
|
||||
error_msg = 'Wiki not found.'
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
owner = wiki.username
|
||||
if owner != username:
|
||||
|
||||
if not check_wiki_admin_permission(wiki, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
wiki.delete()
|
||||
|
||||
repo_id = wiki.repo_id
|
||||
file_name = WIKI_CONFIG_FILE_NAME
|
||||
try:
|
||||
seafile_api.del_file(repo_id, WIKI_CONFIG_PATH,
|
||||
json.dumps([file_name]),
|
||||
request.user.username)
|
||||
except SearpcError as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
org_id = -1
|
||||
if is_org_context(request):
|
||||
org_id = request.user.org.org_id
|
||||
|
||||
if is_group_wiki(wiki):
|
||||
group_id = int(wiki.owner)
|
||||
try:
|
||||
SeafileAPI.delete_group_owned_repo(group_id, wiki.repo_id, org_id)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
else:
|
||||
seafile_api.remove_repo(wiki.repo_id)
|
||||
|
||||
return Response()
|
||||
|
||||
@ -184,7 +256,7 @@ class Wiki2ConfigView(APIView):
|
||||
error_msg = "Wiki not found."
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not can_edit_wiki(wiki, request.user.username):
|
||||
if not check_wiki_permission(wiki, request.user.username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
@ -224,7 +296,7 @@ class Wiki2ConfigView(APIView):
|
||||
error_msg = "Wiki not found."
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not can_edit_wiki(wiki, request.user.username):
|
||||
if not check_wiki_permission(wiki, request.user.username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
@ -327,6 +399,10 @@ class Wiki2PageContentView(APIView):
|
||||
error_msg = "Wiki not found."
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not check_wiki_permission(wiki, request.user.username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
permission = check_folder_permission(request, wiki.repo_id, '/')
|
||||
if not permission:
|
||||
error_msg = 'Permission denied.'
|
||||
@ -424,7 +500,7 @@ class Wiki2PagesView(APIView):
|
||||
error_msg = "Wiki not found."
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not can_edit_wiki(wiki, request.user.username):
|
||||
if not check_wiki_permission(wiki, request.user.username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
@ -488,7 +564,7 @@ class Wiki2PageView(APIView):
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
username = request.user.username
|
||||
if not can_edit_wiki(wiki, username):
|
||||
if not check_wiki_permission(wiki, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
|
@ -4,7 +4,6 @@ from django.utils import timezone
|
||||
from seaserv import seafile_api
|
||||
|
||||
from seahub.base.fields import LowerCaseCharField
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr, datetime_to_isoformat_timestr
|
||||
|
||||
|
||||
@ -13,17 +12,9 @@ class WikiDoesNotExist(Exception):
|
||||
|
||||
|
||||
class WikiManager(models.Manager):
|
||||
def add(self, wiki_name, username, org_id=-1):
|
||||
def add(self, wiki_name, owner, repo_id):
|
||||
now = timezone.now()
|
||||
if org_id and org_id > 0:
|
||||
repo_id = seafile_api.create_org_repo(wiki_name, '', username, org_id)
|
||||
else:
|
||||
repo_id = seafile_api.create_repo(wiki_name, '', username)
|
||||
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
assert repo is not None
|
||||
|
||||
wiki = self.model(username=username, name=wiki_name, repo_id=repo.id, created_at=now)
|
||||
wiki = self.model(owner=owner, name=wiki_name, repo_id=repo_id, created_at=now)
|
||||
wiki.save(using=self._db)
|
||||
return wiki
|
||||
|
||||
@ -33,7 +24,7 @@ class Wiki2(models.Model):
|
||||
personal wiki.
|
||||
"""
|
||||
|
||||
username = LowerCaseCharField(max_length=255)
|
||||
owner = LowerCaseCharField(max_length=255)
|
||||
name = models.CharField(max_length=255)
|
||||
repo_id = models.CharField(max_length=36, db_index=True)
|
||||
created_at = models.DateTimeField(default=timezone.now, db_index=True)
|
||||
@ -41,7 +32,7 @@ class Wiki2(models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = 'wiki_wiki2'
|
||||
unique_together = (('username', 'repo_id'),)
|
||||
unique_together = (('owner', 'repo_id'),)
|
||||
ordering = ["name"]
|
||||
|
||||
@property
|
||||
@ -57,8 +48,7 @@ class Wiki2(models.Model):
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.pk,
|
||||
'owner': self.username,
|
||||
'owner_nickname': email2nickname(self.username),
|
||||
'owner': self.owner,
|
||||
'name': self.name,
|
||||
'created_at': datetime_to_isoformat_timestr(self.created_at),
|
||||
'updated_at': timestamp_to_isoformat_timestr(self.updated_at),
|
||||
|
@ -11,6 +11,7 @@ import posixpath
|
||||
from seaserv import seafile_api
|
||||
from seahub.constants import PERMISSION_READ_WRITE
|
||||
from seahub.utils import gen_inner_file_get_url
|
||||
from seahub.group.utils import is_group_admin, is_group_member
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -56,8 +57,34 @@ def can_edit_wiki(wiki, username):
|
||||
def get_wiki_config(repo_id, username):
|
||||
config_path = posixpath.join(WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME)
|
||||
file_id = seafile_api.get_file_id_by_path(repo_id, config_path)
|
||||
if not file_id:
|
||||
return {}
|
||||
token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True)
|
||||
url = gen_inner_file_get_url(token, WIKI_CONFIG_FILE_NAME)
|
||||
resp = requests.get(url)
|
||||
wiki_config = json.loads(resp.content)
|
||||
return wiki_config
|
||||
|
||||
|
||||
def is_group_wiki(wiki):
|
||||
return not ('@' in wiki.owner)
|
||||
|
||||
|
||||
def check_wiki_admin_permission(wiki, username):
|
||||
if is_group_wiki(wiki):
|
||||
group_id = wiki.owner
|
||||
return is_group_admin(group_id, username)
|
||||
else:
|
||||
if username == wiki.owner:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def check_wiki_permission(wiki, username):
|
||||
if is_group_wiki(wiki):
|
||||
group_id = wiki.owner
|
||||
return is_group_member(group_id, username)
|
||||
else:
|
||||
if username == wiki.owner:
|
||||
return True
|
||||
return False
|
||||
|
@ -18,7 +18,7 @@ from seahub.utils import get_file_type_and_ext, render_permission_error, is_pro_
|
||||
from seahub.utils.file_types import IMAGE, SEADOC
|
||||
from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token
|
||||
from seahub.auth.decorators import login_required
|
||||
from seahub.wiki2.utils import can_edit_wiki
|
||||
from seahub.wiki2.utils import can_edit_wiki, check_wiki_permission
|
||||
|
||||
from seahub.utils.file_op import check_file_lock, ONLINE_OFFICE_LOCK_OWNER, if_locked_by_online_office
|
||||
from seahub.utils.repo import parse_repo_perm
|
||||
@ -38,6 +38,9 @@ def wiki_view(request, wiki_id, file_path):
|
||||
|
||||
# perm check
|
||||
req_user = request.user.username
|
||||
if not check_wiki_permission(wiki, req_user):
|
||||
return render_permission_error(request, 'Permission denied.')
|
||||
|
||||
permission = check_folder_permission(request, wiki.repo_id, '/')
|
||||
if not permission:
|
||||
return render_permission_error(request, 'Permission denied.')
|
||||
|
Loading…
Reference in New Issue
Block a user