1
0
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:
Michael An 2024-05-28 16:31:00 +08:00 committed by GitHub
parent db4ed716aa
commit c604bb2a94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 203 additions and 49 deletions

View File

@ -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>

View File

@ -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}>

View File

@ -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';

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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),

View File

@ -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

View File

@ -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.')