1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-12 13:24:52 +00:00

wiki page saved in doc uuid dir (#6110)

* wiki page saved in doc uuid dir

* optimize del page and dir

* optimize code

* rebase
This commit is contained in:
JoinTyang
2024-05-27 17:19:58 +08:00
committed by GitHub
parent 69011567a3
commit dc0c220364
9 changed files with 238 additions and 90 deletions

View File

@@ -83,14 +83,7 @@ class Wiki extends Component {
getWikiConfig = () => { getWikiConfig = () => {
wikiAPI.getWiki2Config(wikiId).then(res => { wikiAPI.getWiki2Config(wikiId).then(res => {
const { wiki_config, repo_id } = res.data.wiki; const { wiki_config, repo_id } = res.data.wiki;
try { const config = new WikiConfig(wiki_config || {});
JSON.parse(wiki_config);
} catch (error) {
toaster.danger(gettext('Wiki config error'));
this.setState({ isConfigLoading: false });
return;
}
const config = new WikiConfig(JSON.parse(wiki_config) || {});
this.setState({ this.setState({
config, config,
isConfigLoading: false, isConfigLoading: false,

View File

@@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import deepCopy from 'deep-copy'; import deepCopy from 'deep-copy';
import { gettext, repoID, isWiki2 } from '../../utils/constants'; import { gettext, isWiki2, wikiId } from '../../utils/constants';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
// import TreeView from '../../components/tree-view/tree-view'; // import TreeView from '../../components/tree-view/tree-view';
@@ -14,7 +14,7 @@ import ViewStructureFooter from './view-structure/view-structure-footer';
import { generateUniqueId, isObjectNotEmpty } from './utils'; import { generateUniqueId, isObjectNotEmpty } from './utils';
import Folder from './models/folder'; import Folder from './models/folder';
import Page from './models/page'; import Page from './models/page';
import { seafileAPI } from '../../utils/seafile-api'; import wikiAPI from '../../utils/wiki-api';
import { FOLDER } from './constant'; import { FOLDER } from './constant';
import './side-panel.css'; import './side-panel.css';
@@ -101,13 +101,10 @@ class SidePanel extends Component {
const config = deepCopy(this.props.config); const config = deepCopy(this.props.config);
const { pages, navigation } = config; const { pages, navigation } = config;
const index = PageUtils.getPageIndexById(pageId, pages); const index = PageUtils.getPageIndexById(pageId, pages);
const pageIndex = pages.findIndex(item => item.id === pageId);
let path = pages[pageIndex].path;
config.pages.splice(index, 1); config.pages.splice(index, 1);
PageUtils.deletePage(navigation, pageId); PageUtils.deletePage(navigation, pageId);
this.props.saveWikiConfig(config); this.props.saveWikiConfig(config);
seafileAPI.deleteFile(repoID, path); wikiAPI.deleteWiki2Page(wikiId, pageId);
if (config.pages.length > 0) { if (config.pages.length > 0) {
this.props.setCurrentPage(config.pages[0].id); this.props.setCurrentPage(config.pages[0].id);
} else { } else {

View File

@@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalHeader, ModalBody, ModalFooter, Label, Input, Button } from 'reactstrap'; import { Modal, ModalHeader, ModalBody, ModalFooter, Label, Input, Button } from 'reactstrap';
import { gettext, repoID } from '../../../utils/constants'; import { gettext, wikiId } from '../../../utils/constants';
import { seafileAPI } from '../../../utils/seafile-api';
import { Utils } from '../../../utils/utils'; import { Utils } from '../../../utils/utils';
import toaster from '../../../components/toast'; import toaster from '../../../components/toast';
import Loading from '../../../components/loading'; import Loading from '../../../components/loading';
import wikiAPI from '../../../utils/wiki-api';
import '../css/add-new-page-dialog.css'; import '../css/add-new-page-dialog.css';
@@ -14,7 +14,6 @@ const propTypes = {
onAddNewPage: PropTypes.func, onAddNewPage: PropTypes.func,
}; };
const NEW_WIKI_FILE_PATH = '/wiki-pages/';
class AddNewPageDialog extends React.Component { class AddNewPageDialog extends React.Component {
@@ -22,35 +21,11 @@ class AddNewPageDialog extends React.Component {
super(props); super(props);
this.state = { this.state = {
pageName: '', pageName: '',
isLoading: true, isLoading: false,
errMessage: '', errMessage: '',
}; };
} }
componentDidMount() {
seafileAPI.getDirInfo(repoID, NEW_WIKI_FILE_PATH).then((res) => {
if (res.data.path === NEW_WIKI_FILE_PATH) {
this.setState({ isLoading: false });
}
}).catch((error) => {
if (error.response.data.error_msg === 'Folder /wiki-pages/ not found.') {
seafileAPI.createDir(repoID, NEW_WIKI_FILE_PATH).then((res) => {
if (res.data === 'success') {
this.setState({ isLoading: false });
}
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
this.setState({ isLoading: false });
});
} else {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
this.setState({ isLoading: false });
}
});
}
handleChange = (event) => { handleChange = (event) => {
let value = event.target.value; let value = event.target.value;
if (value !== this.state.pageName) { if (value !== this.state.pageName) {
@@ -89,12 +64,12 @@ class AddNewPageDialog extends React.Component {
const pageName = this.state.pageName.trim(); const pageName = this.state.pageName.trim();
if (this.checkName(pageName)) { if (this.checkName(pageName)) {
this.setState({ isLoading: true }); this.setState({ isLoading: true });
this.createFile(pageName, `${NEW_WIKI_FILE_PATH}${pageName}.sdoc`); this.createPage(pageName);
} }
}; };
createFile = (pageName, filePath) => { createPage = (pageName) => {
seafileAPI.createFile(repoID, filePath).then(res => { wikiAPI.createWiki2Page(wikiId, pageName).then(res => {
const { obj_name, parent_dir, doc_uuid } = res.data; const { obj_name, parent_dir, doc_uuid } = res.data;
this.props.onAddNewPage({ this.props.onAddNewPage({
name: pageName, name: pageName,

View File

@@ -41,7 +41,7 @@ class Wikis extends Component {
return wiki['version'] = 'v1'; return wiki['version'] = 'v1';
}); });
wikiAPI.listWikis2().then(res => { wikiAPI.listWikis2().then(res => {
let wikis2 = res.data.data; let wikis2 = res.data.wikis;
wikis2.map(wiki => { wikis2.map(wiki => {
return wiki['version'] = 'v2'; return wiki['version'] = 'v2';
}); });

View File

@@ -108,9 +108,9 @@ class WikiAPI {
// for wiki2 // for wiki2
listWiki2Dir(wikiId, dirPath, withParents) { listWiki2Dir(wikiId, dirPath, withParents) {
const path = encodeURIComponent(dirPath); const path = encodeURIComponent(dirPath);
let url = this.server + '/api/v2.1/wikis2/' + wikiId + '/dir/?p=' + path; let url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page-dir/?p=' + path;
if (withParents) { if (withParents) {
url = this.server + '/api/v2.1/wikis2/' + wikiId + '/dir/?p=' + path + '&with_parents=' + withParents; url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page-dir/?p=' + path + '&with_parents=' + withParents;
} }
return this.req.get(url); return this.req.get(url);
} }
@@ -119,7 +119,7 @@ class WikiAPI {
getWiki2FileContent(wikiId, filePath) { getWiki2FileContent(wikiId, filePath) {
const path = encodeURIComponent(filePath); const path = encodeURIComponent(filePath);
const time = new Date().getTime(); const time = new Date().getTime();
const url = this.server + '/api/v2.1/wikis2/' + wikiId + '/content/' + '?p=' + path + '&_=' + time; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/content/' + '?p=' + path + '&_=' + time;
return this.req.get(url); return this.req.get(url);
} }
@@ -161,12 +161,12 @@ class WikiAPI {
} }
deleteWiki2(wikiId) { deleteWiki2(wikiId) {
const url = this.server + '/api/v2.1/wikis2/' + wikiId + '/'; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/';
return this.req.delete(url); return this.req.delete(url);
} }
updateWiki2Config(wikiId, wikiConfig) { updateWiki2Config(wikiId, wikiConfig) {
const url = this.server + '/api/v2.1/wiki2-config/' + wikiId + '/'; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/config/';
let params = { let params = {
wiki_config: wikiConfig wiki_config: wikiConfig
}; };
@@ -174,10 +174,28 @@ class WikiAPI {
} }
getWiki2Config(wikiId) { getWiki2Config(wikiId) {
const url = this.server + '/api/v2.1/wiki2-config/' + wikiId + '/'; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/config/';
return this.req.get(url); return this.req.get(url);
} }
createWiki2Page(wikiId, pageName) {
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/pages/';
let form = new FormData();
form.append('page_name', pageName);
return this._sendPostRequest(url, form);
}
deleteWiki2Page(wikiId, pageId) {
// const path = encodeURIComponent(pagePath);
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page/' + pageId + '/';
return this.req.delete(url);
}
deleteWiki2Folder(wikiId, folderId) {
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/folder/' + folderId + '/';
return this.req.delete(url);
}
} }
let wikiAPI = new WikiAPI(); let wikiAPI = new WikiAPI();

View File

@@ -6,11 +6,12 @@ import logging
import requests import requests
import posixpath import posixpath
import time import time
import uuid
import urllib.request, urllib.error, urllib.parse import urllib.request, urllib.error, urllib.parse
from rest_framework import status from rest_framework import status
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated, IsAuthenticated, IsAuthenticatedOrReadOnly from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from seaserv import seafile_api, edit_repo from seaserv import seafile_api, edit_repo
@@ -21,9 +22,10 @@ from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error, to_python_boolean from seahub.api2.utils import api_error, to_python_boolean
from seahub.wiki2.models import Wiki2 as Wiki 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 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
from seahub.utils import is_org_context, get_user_repos, gen_inner_file_get_url, gen_file_upload_url, \ 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 normalize_dir_path, is_pro_version, check_filename_with_rename, is_valid_dirent_name
from seahub.views import check_folder_permission from seahub.views import check_folder_permission
from seahub.views.file import send_file_access_msg from seahub.views.file import send_file_access_msg
from seahub.base.templatetags.seahub_tags import email2nickname from seahub.base.templatetags.seahub_tags import email2nickname
@@ -32,10 +34,12 @@ from seahub.utils.repo import parse_repo_perm
from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token 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
from seahub.seadoc.sdoc_server_api import SdocServerAPI 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
WIKI_CONFIG_PATH = '_Internal/Wiki'
WIKI_CONFIG_FILE_NAME = 'index.json'
HTTP_520_OPERATION_FAILED = 520 HTTP_520_OPERATION_FAILED = 520
@@ -91,10 +95,9 @@ class Wikis2View(APIView):
wiki_list = [] wiki_list = []
for wiki in wikis: for wiki in wikis:
wiki_info = wiki.to_dict() wiki_info = wiki.to_dict()
wiki_info['can_edit'] = (username == wiki.username)
wiki_list.append(wiki_info) wiki_list.append(wiki_info)
return Response({'data': wiki_list}) return Response({'wikis': wiki_list})
def post(self, request, format=None): def post(self, request, format=None):
"""Add a new wiki. """Add a new wiki.
@@ -169,8 +172,12 @@ class Wiki2ConfigView(APIView):
def put(self, request, wiki_id): def put(self, request, wiki_id):
"""Edit a wiki config """Edit a wiki config
""" """
username = request.user.username wiki_config = request.data.get('wiki_config')
if not wiki_config:
error_msg = 'wiki_config invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
username = request.user.username
try: try:
wiki = Wiki.objects.get(id=wiki_id) wiki = Wiki.objects.get(id=wiki_id)
except Wiki.DoesNotExist: except Wiki.DoesNotExist:
@@ -195,8 +202,6 @@ class Wiki2ConfigView(APIView):
upload_link = gen_file_upload_url(token, 'upload-api') upload_link = gen_file_upload_url(token, 'upload-api')
upload_link = upload_link + '?replace=1' upload_link = upload_link + '?replace=1'
wiki_config = request.data.get('wiki_config', '{}')
files = { files = {
'file': (WIKI_CONFIG_FILE_NAME, wiki_config) 'file': (WIKI_CONFIG_FILE_NAME, wiki_config)
} }
@@ -223,7 +228,6 @@ class Wiki2ConfigView(APIView):
error_msg = 'Permission denied.' error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
path = posixpath.join(WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME)
try: try:
repo = seafile_api.get_repo(wiki.repo_id) repo = seafile_api.get_repo(wiki.repo_id)
if not repo: if not repo:
@@ -233,29 +237,10 @@ class Wiki2ConfigView(APIView):
error_msg = _("Internal Server Error") error_msg = _("Internal Server Error")
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try:
file_id = seafile_api.get_file_id_by_path(repo.repo_id, path)
except SearpcError as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
wiki = wiki.to_dict() wiki = wiki.to_dict()
if not file_id: wiki_config = get_wiki_config(repo.repo_id, request.user.username)
wiki['wiki_config'] = '{}'
return Response({'wiki': wiki})
token = seafile_api.get_fileserver_access_token(repo.repo_id, file_id, 'download', request.user.username, use_onetime=True) wiki['wiki_config'] = wiki_config
if not token:
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
url = gen_inner_file_get_url(token, WIKI_CONFIG_FILE_NAME)
resp = requests.get(url)
content = resp.content
wiki['wiki_config'] = content
return Response({'wiki': wiki}) return Response({'wiki': wiki})
@@ -402,3 +387,155 @@ class Wiki2PageContentView(APIView):
"seadoc_access_token": seadoc_access_token, "seadoc_access_token": seadoc_access_token,
"assets_url": assets_url, "assets_url": assets_url,
}) })
class Wiki2PagesView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get_file_info(self, repo_id, file_path):
file_obj = seafile_api.get_dirent_by_path(repo_id, file_path)
if file_obj:
file_name = file_obj.obj_name
else:
file_name = os.path.basename(file_path.rstrip('/'))
file_info = {
'repo_id': repo_id,
'parent_dir': os.path.dirname(file_path),
'obj_name': file_name,
'mtime': timestamp_to_isoformat_timestr(file_obj.mtime) if file_obj else ''
}
return file_info
def post(self, request, wiki_id):
page_name = request.data.get('page_name', None)
if not page_name or '/' in page_name or '\\' in page_name:
error_msg = 'page_name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
try:
wiki = Wiki.objects.get(id=wiki_id)
except Wiki.DoesNotExist:
error_msg = "Wiki not found."
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not can_edit_wiki(wiki, request.user.username):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo_id = wiki.repo_id
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
sdoc_uuid = uuid.uuid4()
file_name = page_name + '.sdoc'
parent_dir = os.path.join(WIKI_PAGES_DIR, str(sdoc_uuid))
path = os.path.join(parent_dir, file_name)
seafile_api.mkdir_with_parents(repo_id, '/', parent_dir.strip('/'), request.user.username)
new_file_name = check_filename_with_rename(repo_id, parent_dir, file_name)
# create new empty file
if not is_valid_dirent_name(new_file_name):
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name)
try:
seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, request.user.username)
except Exception as e:
if str(e) == 'Too many files in library.':
error_msg = _("The number of files in library exceeds the limit")
return api_error(HTTP_447_TOO_MANY_FILES_IN_LIBRARY, error_msg)
else:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
new_file_path = posixpath.join(parent_dir, new_file_name)
file_info = self.get_file_info(repo_id, new_file_path)
file_info['doc_uuid'] = sdoc_uuid
filename = os.path.basename(path)
try:
FileUUIDMap.objects.create_fileuuidmap_by_uuid(sdoc_uuid, repo_id, parent_dir, filename, is_dir=False)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response(file_info)
class Wiki2PageView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def delete(self, request, wiki_id, page_id):
try:
wiki = Wiki.objects.get(id=wiki_id)
except Wiki.DoesNotExist:
error_msg = "Wiki not found."
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
username = request.user.username
if not can_edit_wiki(wiki, username):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo_id = wiki.repo_id
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
wiki_config = get_wiki_config(repo_id, username)
pages = wiki_config.get('pages', [])
page_info = next(filter(lambda t: t['id'] == page_id, pages), {})
path = page_info.get('path')
# check file lock
try:
is_locked, locked_by_me = check_file_lock(repo_id, path, username)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
if is_locked and not locked_by_me:
error_msg = _("File is locked")
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
sdoc_dir_path = os.path.dirname(path)
parent_dir = os.path.dirname(sdoc_dir_path)
dir_name = os.path.basename(sdoc_dir_path)
# delete the folder where the sdoc is located
try:
seafile_api.del_file(repo_id, parent_dir, json.dumps([dir_name]), username)
except SearpcError as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
try: # rm sdoc fileuuid
file_name = os.path.basename(path)
file_uuid = get_seadoc_file_uuid(repo, path)
FileComment.objects.filter(uuid=file_uuid).delete()
FileUUIDMap.objects.delete_fileuuidmap_by_path(repo_id, sdoc_dir_path, file_name, is_dir=False)
SeadocHistoryName.objects.filter(doc_uuid=file_uuid).delete()
SeadocDraft.objects.filter(doc_uuid=file_uuid).delete()
SeadocCommentReply.objects.filter(doc_uuid=file_uuid).delete()
except Exception as e:
logger.error(e)
return Response({'success': True})

View File

@@ -40,6 +40,11 @@ class FileUUIDMapManager(models.Manager):
uuid.save(using=self._db) uuid.save(using=self._db)
return uuid return uuid
def create_fileuuidmap_by_uuid(self, file_uuid, repo_id, parent_path, filename, is_dir):
repo_id, parent_path = self.model.get_origin_repo_id_and_parent_path(repo_id, parent_path)
file_map = self.model(uuid=file_uuid, repo_id=repo_id, parent_path=parent_path, filename=filename, is_dir=is_dir)
file_map.save(using=self._db)
def get_fileuuidmap_by_path(self, repo_id, parent_path, filename, is_dir): def get_fileuuidmap_by_path(self, repo_id, parent_path, filename, is_dir):
""" get filemap uuid by repoid、 parent_path 、 filename 、is_dir """ get filemap uuid by repoid、 parent_path 、 filename 、is_dir
args: args:

View File

@@ -204,7 +204,8 @@ from seahub.ocm.settings import OCM_ENDPOINT
from seahub.ai.apis import LibrarySdocIndexes, Search, LibrarySdocIndex, TaskStatus, \ from seahub.ai.apis import LibrarySdocIndexes, Search, LibrarySdocIndex, TaskStatus, \
LibraryIndexState, QuestionAnsweringSearchInLibrary, FileDownloadToken LibraryIndexState, QuestionAnsweringSearchInLibrary, FileDownloadToken
from seahub.wiki2.views import wiki_view from seahub.wiki2.views import wiki_view
from seahub.api2.endpoints.wiki2 import Wikis2View, Wiki2View, Wiki2ConfigView, Wiki2PagesDirView, Wiki2PageContentView from seahub.api2.endpoints.wiki2 import Wikis2View, Wiki2View, Wiki2ConfigView, Wiki2PagesDirView, Wiki2PageContentView,\
Wiki2PagesView, Wiki2PageView
from seahub.api2.endpoints.subscription import SubscriptionView, SubscriptionPlansView, SubscriptionLogsView from seahub.api2.endpoints.subscription import SubscriptionView, SubscriptionPlansView, SubscriptionLogsView
urlpatterns = [ urlpatterns = [
@@ -521,10 +522,12 @@ urlpatterns = [
## user::wiki2 ## user::wiki2
re_path(r'^api/v2.1/wikis2/$', Wikis2View.as_view(), name='api-v2.1-wikis2'), re_path(r'^api/v2.1/wikis2/$', Wikis2View.as_view(), name='api-v2.1-wikis2'),
re_path(r'^api/v2.1/wikis2/(?P<wiki_id>\d+)/$', Wiki2View.as_view(), name='api-v2.1-wiki2'), re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/$', Wiki2View.as_view(), name='api-v2.1-wiki2'),
re_path(r'^api/v2.1/wikis2/(?P<wiki_id>\d+)/dir/$', Wiki2PagesDirView.as_view(), name='api-v2.1-wiki2-pages-dir'), re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/page-dir/$', Wiki2PagesDirView.as_view(), name='api-v2.1-wiki2-pages-dir'),
re_path(r'^api/v2.1/wiki2-config/(?P<wiki_id>\d+)/$', Wiki2ConfigView.as_view(), name='api-v2.1-wiki2-config'), re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/config/$', Wiki2ConfigView.as_view(), name='api-v2.1-wiki2-config'),
re_path(r'^api/v2.1/wikis2/(?P<wiki_id>\d+)/content/$', Wiki2PageContentView.as_view(), name='api-v2.1-wiki2-pages-content'), re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/content/$', Wiki2PageContentView.as_view(), name='api-v2.1-wiki2-pages-content'),
re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/pages/$', Wiki2PagesView.as_view(), name='api-v2.1-wiki2-pages'),
re_path(r'^api/v2.1/wiki2/(?P<wiki_id>\d+)/page/(?P<page_id>[-0-9a-zA-Z]{4})/$', Wiki2PageView.as_view(), name='api-v2.1-wiki2-page'),
## user::drafts ## user::drafts
re_path(r'^api/v2.1/drafts/$', DraftsView.as_view(), name='api-v2.1-drafts'), re_path(r'^api/v2.1/drafts/$', DraftsView.as_view(), name='api-v2.1-drafts'),

View File

@@ -1,15 +1,25 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re import re
import os
import stat import stat
import logging import logging
import json
import requests
import posixpath
from seaserv import seafile_api from seaserv import seafile_api
from seahub.constants import PERMISSION_READ_WRITE from seahub.constants import PERMISSION_READ_WRITE
from seahub.utils import gen_inner_file_get_url
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
WIKI_PAGES_DIR = '/wiki-pages'
WIKI_CONFIG_PATH = '_Internal/Wiki'
WIKI_CONFIG_FILE_NAME = 'index.json'
def is_valid_wiki_name(name): def is_valid_wiki_name(name):
name = name.strip() name = name.strip()
if len(name) > 255 or len(name) < 1: if len(name) > 255 or len(name) < 1:
@@ -41,3 +51,13 @@ def get_wiki_dirs_by_path(repo_id, path, all_dirs):
def can_edit_wiki(wiki, username): def can_edit_wiki(wiki, username):
permission = seafile_api.check_permission_by_path(wiki.repo_id, '/', username) permission = seafile_api.check_permission_by_path(wiki.repo_id, '/', username)
return permission == PERMISSION_READ_WRITE return permission == PERMISSION_READ_WRITE
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)
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