From cc625f7815daa32ddb932e23d1e7f205f88deb75 Mon Sep 17 00:00:00 2001
From: JoinTyang <41655440+JoinTyang@users.noreply.github.com>
Date: Tue, 5 Nov 2024 18:03:53 +0800
Subject: [PATCH] migrate old wiki to new wiki (#6987)
* migrate old wiki to new wiki
* change style
---------
Co-authored-by: Michael An <2331806369@qq.com>
---
.../src/components/common/select/index.js | 4 +-
.../common/select/no-group-message.js | 3 +-
.../common/select/seahub-select-style.js | 8 +-
.../src/components/dialog/add-wiki-dialog.js | 4 +-
.../components/dialog/convert-wiki-dialog.js | 114 ++++++++++++++
frontend/src/components/modal-portal.js | 2 +-
frontend/src/components/user-select.js | 7 +-
.../wiki-card-view/wiki-card-group.js | 7 +-
.../wiki-card-view/wiki-card-item.js | 29 ++++
.../wiki-card-view/wiki-card-view.js | 2 +
frontend/src/pages/wikis/wikis.js | 12 ++
frontend/src/utils/wiki-api.js | 10 ++
seahub/api2/endpoints/wiki2.py | 147 +++++++++++++++++-
seahub/urls.py | 10 +-
seahub/wiki2/utils.py | 15 +-
15 files changed, 351 insertions(+), 23 deletions(-)
create mode 100644 frontend/src/components/dialog/convert-wiki-dialog.js
diff --git a/frontend/src/components/common/select/index.js b/frontend/src/components/common/select/index.js
index 17d8a9bfe1..6764f95dcd 100644
--- a/frontend/src/components/common/select/index.js
+++ b/frontend/src/components/common/select/index.js
@@ -1,5 +1,5 @@
import SeahubSelect from './seahub-select';
import { NoGroupMessage } from './no-group-message';
-import { MenuSelectStyle, UserSelectStyle } from './seahub-select-style';
+import { MenuSelectStyle, UserSelectStyle, NoOptionsStyle } from './seahub-select-style';
-export { SeahubSelect, NoGroupMessage, MenuSelectStyle, UserSelectStyle };
+export { SeahubSelect, NoGroupMessage, MenuSelectStyle, UserSelectStyle, NoOptionsStyle };
diff --git a/frontend/src/components/common/select/no-group-message.js b/frontend/src/components/common/select/no-group-message.js
index 362f72a5e3..7f97e853fd 100644
--- a/frontend/src/components/common/select/no-group-message.js
+++ b/frontend/src/components/common/select/no-group-message.js
@@ -1,10 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../../utils/constants';
+import { NoOptionsStyle } from './seahub-select-style';
const NoGroupMessage = (props) => {
return (
-
{gettext('Group not found')}
+ {gettext('Group not found')}
);
};
diff --git a/frontend/src/components/common/select/seahub-select-style.js b/frontend/src/components/common/select/seahub-select-style.js
index df4130841e..b2aa726170 100644
--- a/frontend/src/components/common/select/seahub-select-style.js
+++ b/frontend/src/components/common/select/seahub-select-style.js
@@ -87,4 +87,10 @@ const UserSelectStyle = {
},
};
-export { MenuSelectStyle, UserSelectStyle };
+const NoOptionsStyle = {
+ margin: '6px 10px',
+ textAlign: 'center',
+ color: 'hsl(0, 0%, 50%)',
+};
+
+export { MenuSelectStyle, UserSelectStyle, NoOptionsStyle };
diff --git a/frontend/src/components/dialog/add-wiki-dialog.js b/frontend/src/components/dialog/add-wiki-dialog.js
index e37039a3e6..c8b1321023 100644
--- a/frontend/src/components/dialog/add-wiki-dialog.js
+++ b/frontend/src/components/dialog/add-wiki-dialog.js
@@ -5,7 +5,7 @@ import { gettext, isPro } from '../../utils/constants';
import wikiAPI from '../../utils/wiki-api';
import { Utils } from '../../utils/utils';
import toaster from '../toast';
-import { SeahubSelect } from '../common/select';
+import { SeahubSelect, NoOptionsStyle } from '../common/select';
const propTypes = {
toggleCancel: PropTypes.func.isRequired,
@@ -97,7 +97,7 @@ class AddWikiDialog extends React.Component {
maxMenuHeight={200}
value={this.state.selectedOption}
components={{ NoOptionsMessage: (
- {gettext('No department')}
+ {gettext('No department')}
) }}
noOptionsMessage={() => {return gettext('No options available');}}
/>
diff --git a/frontend/src/components/dialog/convert-wiki-dialog.js b/frontend/src/components/dialog/convert-wiki-dialog.js
new file mode 100644
index 0000000000..1efd83263f
--- /dev/null
+++ b/frontend/src/components/dialog/convert-wiki-dialog.js
@@ -0,0 +1,114 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Input, Label } from 'reactstrap';
+import { gettext, isPro } from '../../utils/constants';
+import wikiAPI from '../../utils/wiki-api';
+import { Utils } from '../../utils/utils';
+import toaster from '../toast';
+import { SeahubSelect, NoOptionsStyle } from '../common/select';
+
+const propTypes = {
+ toggleCancel: PropTypes.func.isRequired,
+ convertWiki: PropTypes.func.isRequired,
+ wiki: PropTypes.object.isRequired,
+};
+
+class ConvertWikiDialog extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ name: '',
+ isSubmitBtnActive: false,
+ selectedOption: null,
+ options: [],
+ };
+ }
+
+ componentDidMount() {
+ if (!isPro) return;
+ wikiAPI.listWikiDepartments().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.email = departments[i].email;
+ obj.label = departments[i].name;
+ options.push(obj);
+ }
+ this.setState({ options });
+ }).catch(error => {
+ let errMessage = Utils.getErrorMsg(error);
+ toaster.danger(errMessage);
+ });
+ }
+
+ inputNewName = (e) => {
+ this.setState({
+ name: e.target.value,
+ });
+ };
+
+ handleKeyDown = (e) => {
+ if (e.key === 'Enter') {
+ this.handleSubmit(e);
+ }
+ };
+
+ handleSubmit = (e) => {
+ const wikiName = this.state.name.trim();
+ const departmentID = this.state.selectedOption ? this.state.selectedOption.id : null;
+ if (!wikiName) return;
+ this.props.convertWiki(this.props.wiki, wikiName, departmentID);
+ this.props.toggleCancel(e);
+ };
+
+ toggle = () => {
+ this.props.toggleCancel();
+ };
+
+ handleSelectChange = (option) => {
+ this.setState({ selectedOption: option });
+ };
+
+ render() {
+ return (
+
+ {gettext('Convert Wiki')}
+
+
+
+ {isPro &&
+ <>
+
+ {gettext('No department')}
+ ) }}
+ noOptionsMessage={() => {return gettext('No options available');}}
+ />
+ >
+ }
+
+
+
+
+
+
+ );
+ }
+}
+
+ConvertWikiDialog.propTypes = propTypes;
+
+export default ConvertWikiDialog;
diff --git a/frontend/src/components/modal-portal.js b/frontend/src/components/modal-portal.js
index 284fbbc57c..a37c3f076e 100644
--- a/frontend/src/components/modal-portal.js
+++ b/frontend/src/components/modal-portal.js
@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
const propTypes = {
- children: PropTypes.object.isRequired,
+ children: PropTypes.any.isRequired,
};
const modalRoot = document.getElementById('modal-wrapper');
diff --git a/frontend/src/components/user-select.js b/frontend/src/components/user-select.js
index 4e5f165de6..eceefb4bc9 100644
--- a/frontend/src/components/user-select.js
+++ b/frontend/src/components/user-select.js
@@ -5,7 +5,7 @@ import { seafileAPI } from '../utils/seafile-api';
import { gettext, enableShowContactEmailWhenSearchUser, enableShowLoginIDWhenSearchUser } from '../utils/constants';
import { Utils } from '../utils/utils';
import toaster from './toast';
-import { UserSelectStyle } from './common/select';
+import { UserSelectStyle, NoOptionsStyle } from './common/select';
import '../css/user-select.css';
@@ -86,7 +86,6 @@ class UserSelect extends React.Component {
render() {
const searchValue = this.state.searchValue;
- const style = { margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)' };
return (
{
return (
- {searchValue ? gettext('User not found') : gettext('Enter characters to start searching')}
+
+ {searchValue ? gettext('User not found') : gettext('Enter characters to start searching')}
+
);
}
}}
diff --git a/frontend/src/components/wiki-card-view/wiki-card-group.js b/frontend/src/components/wiki-card-view/wiki-card-group.js
index 923648bdae..fa886966df 100644
--- a/frontend/src/components/wiki-card-view/wiki-card-group.js
+++ b/frontend/src/components/wiki-card-view/wiki-card-group.js
@@ -14,6 +14,7 @@ const propTypes = {
isDepartment: PropTypes.bool.isRequired,
isShowAvatar: PropTypes.bool.isRequired,
renameWiki: PropTypes.func.isRequired,
+ convertWiki: PropTypes.func,
toggelAddWikiDialog: PropTypes.func,
sidePanelRate: PropTypes.number,
isSidePanelFolded: PropTypes.bool,
@@ -78,7 +79,10 @@ class WikiCardGroup extends Component {
isDepartment={isDepartment}
isShowAvatar={this.props.isShowAvatar}
renameWiki={this.props.renameWiki}
- /> :
+ :
+
);
})}
diff --git a/frontend/src/components/wiki-card-view/wiki-card-item.js b/frontend/src/components/wiki-card-view/wiki-card-item.js
index dda8560436..1284a071ab 100644
--- a/frontend/src/components/wiki-card-view/wiki-card-item.js
+++ b/frontend/src/components/wiki-card-view/wiki-card-item.js
@@ -11,6 +11,7 @@ import ShareWikiDialog from '../dialog/share-wiki-dialog';
import PublishWikiDialog from '../dialog/publish-wiki-dialog';
import wikiAPI from '../../utils/wiki-api';
import toaster from '../toast';
+import ConvertWikiDialog from '../dialog/convert-wiki-dialog';
dayjs.extend(relativeTime);
@@ -20,6 +21,7 @@ const propTypes = {
deleteWiki: PropTypes.func.isRequired,
unshareGroupWiki: PropTypes.func.isRequired,
renameWiki: PropTypes.func.isRequired,
+ convertWiki: PropTypes.func,
isDepartment: PropTypes.bool.isRequired,
isShowAvatar: PropTypes.bool.isRequired,
};
@@ -33,6 +35,7 @@ class WikiCardItem extends Component {
isItemMenuShow: false,
isShowShareDialog: false,
isShowPublishDialog: false,
+ isShowConvertDialog: false,
customUrl: '',
};
}
@@ -56,6 +59,13 @@ class WikiCardItem extends Component {
});
};
+ onConvertToggle = (e) => {
+ e && e.preventDefault();
+ this.setState({
+ isShowConvertDialog: !this.state.isShowConvertDialog,
+ });
+ };
+
onPublishToggle = (e) => {
this.getPublishWikiLink();
};
@@ -176,6 +186,7 @@ class WikiCardItem extends Component {
let showLeaveShare = false;
let showDropdownMenu = false;
let showPublish = false;
+ let showWikiConvert = false;
if (isDepartment) {
if (isAdmin) {
@@ -184,6 +195,9 @@ class WikiCardItem extends Component {
showShare = true;
showRename = true;
showPublish = true;
+ if (isOldVersion) {
+ showWikiConvert = true;
+ }
} else {
showLeaveShare = true;
}
@@ -194,6 +208,9 @@ class WikiCardItem extends Component {
showDelete = true;
showRename = true;
showPublish = true;
+ if (isOldVersion) {
+ showWikiConvert = true;
+ }
} else {
showLeaveShare = true;
}
@@ -239,6 +256,9 @@ class WikiCardItem extends Component {
{showDelete &&
{gettext('Delete')}
}
+ {showWikiConvert &&
+ {gettext('Convert to new Wiki')}
+ }
{showLeaveShare &&
{gettext('Leave')}
}
@@ -327,6 +347,15 @@ class WikiCardItem extends Component {
/>
}
+ {this.state.isShowConvertDialog &&
+
+
+
+ }
>
);
}
diff --git a/frontend/src/components/wiki-card-view/wiki-card-view.js b/frontend/src/components/wiki-card-view/wiki-card-view.js
index 3139c58076..c18f919383 100644
--- a/frontend/src/components/wiki-card-view/wiki-card-view.js
+++ b/frontend/src/components/wiki-card-view/wiki-card-view.js
@@ -14,6 +14,7 @@ const propTypes = {
renameWiki: PropTypes.func.isRequired,
leaveSharedWiki: PropTypes.func.isRequired,
unshareGroupWiki: PropTypes.func.isRequired,
+ convertWiki: PropTypes.func.isRequired,
toggelAddWikiDialog: PropTypes.func,
sidePanelRate: PropTypes.number,
isSidePanelFolded: PropTypes.bool,
@@ -132,6 +133,7 @@ class WikiCardView extends Component {
deleteWiki={this.props.deleteWiki}
renameWiki={this.props.renameWiki}
unshareGroupWiki={this.props.unshareGroupWiki}
+ convertWiki={this.props.convertWiki}
isSidePanelFolded={isSidePanelFolded}
sidePanelRate={sidePanelRate}
wikis={v1Wikis}
diff --git a/frontend/src/pages/wikis/wikis.js b/frontend/src/pages/wikis/wikis.js
index 9c8f07d241..1823323606 100644
--- a/frontend/src/pages/wikis/wikis.js
+++ b/frontend/src/pages/wikis/wikis.js
@@ -249,6 +249,17 @@ class Wikis extends Component {
}
};
+ convertWiki = (wiki, wikiName, departmentID) => {
+ wikiAPI.convertWiki(wiki.id, wikiName, departmentID).then((res) => {
+ this.getWikis();
+ }).catch((error) => {
+ if (error.response) {
+ let errorMsg = error.response.data.error_msg;
+ toaster.danger(errorMsg);
+ }
+ });
+ };
+
toggleDropdownMenu = (e) => {
e.stopPropagation();
this.setState({
@@ -299,6 +310,7 @@ class Wikis extends Component {
leaveSharedWiki={this.leaveSharedWiki}
unshareGroupWiki={this.unshareGroupWiki}
renameWiki={this.renameWiki}
+ convertWiki={this.convertWiki}
toggelAddWikiDialog={this.toggelAddWikiDialog}
sidePanelRate={this.props.sidePanelRate}
isSidePanelFolded={this.props.isSidePanelFolded}
diff --git a/frontend/src/utils/wiki-api.js b/frontend/src/utils/wiki-api.js
index c93e02d521..34b6eefbfb 100644
--- a/frontend/src/utils/wiki-api.js
+++ b/frontend/src/utils/wiki-api.js
@@ -280,6 +280,16 @@ class WikiAPI {
return this.req.delete(url);
}
+ convertWiki(oldWikiId, wikiName, owner) {
+ const url = this.server + '/api/v2.1/convert-wiki/';
+ let form = new FormData();
+ form.append('old_wiki_id', oldWikiId);
+ form.append('name', wikiName);
+ if (owner) {
+ form.append('owner', owner);
+ }
+ return this._sendPostRequest(url, form);
+ }
}
let wikiAPI = new WikiAPI();
diff --git a/seahub/api2/endpoints/wiki2.py b/seahub/api2/endpoints/wiki2.py
index 7cff66e773..cbee2dac25 100644
--- a/seahub/api2/endpoints/wiki2.py
+++ b/seahub/api2/endpoints/wiki2.py
@@ -25,11 +25,12 @@ from seahub.api2.utils import api_error, is_wiki_repo
from seahub.api2.endpoints.utils import wiki_search
from seahub.utils.db_api import SeafileDB
from seahub.wiki2.models import Wiki2 as Wiki
+from seahub.wiki.models import Wiki as OldWiki
from seahub.wiki2.models import WikiPageTrash, Wiki2Publish
from seahub.wiki2.utils import is_valid_wiki_name, get_wiki_config, WIKI_PAGES_DIR, is_group_wiki, \
check_wiki_admin_permission, check_wiki_permission, get_all_wiki_ids, get_and_gen_page_nav_by_id, \
get_current_level_page_ids, save_wiki_config, gen_unique_id, gen_new_page_nav_by_id, pop_nav, \
- delete_page, move_nav, revert_nav, get_sub_ids_by_page_id, get_parent_id_stack
+ delete_page, move_nav, revert_nav, get_sub_ids_by_page_id, get_parent_id_stack, add_convert_wiki_task
from seahub.utils import is_org_context, get_user_repos, is_pro_version, is_valid_dirent_name, \
get_no_duplicate_obj_name
@@ -37,7 +38,7 @@ from seahub.utils import is_org_context, get_user_repos, is_pro_version, is_vali
from seahub.views import check_folder_permission
from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.utils.file_op import check_file_lock
-from seahub.utils.repo import get_repo_owner, is_valid_repo_id_format
+from seahub.utils.repo import get_repo_owner, is_valid_repo_id_format, is_group_repo_staff, is_repo_owner
from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token, copy_sdoc_images_with_sdoc_uuid
from seahub.settings import ENABLE_STORAGE_CLASSES, STORAGE_CLASS_MAPPING_POLICY, \
ENCRYPTED_LIBRARY_VERSION
@@ -51,6 +52,7 @@ 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
from seaserv import ccnet_api
+from seahub.share.utils import is_repo_admin
HTTP_520_OPERATION_FAILED = 520
@@ -59,7 +61,7 @@ logger = logging.getLogger(__name__)
def _merge_wiki_in_groups(group_wikis, publish_wiki_ids):
-
+
group_ids = [gw.group_id for gw in group_wikis]
group_id_wikis_map = {key: [] for key in group_ids}
for gw in group_wikis:
@@ -81,7 +83,7 @@ def _merge_wiki_in_groups(group_wikis, publish_wiki_ids):
group_id = gw.group_id
group_id_wikis_map[group_id].append(wiki_info)
return group_id_wikis_map
-
+
@@ -96,7 +98,7 @@ class Wikis2View(APIView):
username = request.user.username
org_id = request.user.org.org_id if is_org_context(request) else None
(owned, shared, groups, public) = get_user_repos(username, org_id)
-
+
# list user groups
if is_org_context(request):
org_id = request.user.org.org_id
@@ -623,7 +625,7 @@ class Wiki2PagesView(APIView):
if move_position not in valid_move_positions:
error_msg = 'Invalid move_position value: ' + move_position
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
-
+
if (target_page_id not in id_set) or (moved_page_id not in id_set):
error_msg = 'Page not found'
logger.error(error_msg)
@@ -1311,3 +1313,136 @@ class WikiSearch(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
return Response(resp_json, resp.status_code)
+
+
+class WikiConvertView(APIView):
+ authentication_classes = (TokenAuthentication, SessionAuthentication)
+ permission_classes = (IsAuthenticated,)
+ throttle_classes = (UserRateThrottle,)
+
+ def post(self, request):
+ old_wiki_id = request.data.get('old_wiki_id', None)
+ if not old_wiki_id:
+ error_msg = 'old_wiki_id invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ try:
+ wiki = OldWiki.objects.get(id=old_wiki_id)
+ except OldWiki.DoesNotExist:
+ error_msg = 'Old Wiki not found.'
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ username = request.user.username
+ old_repo_id = wiki.repo_id
+
+ # check old wiki permission
+ is_owner = is_repo_owner(request, old_repo_id, username)
+ if not is_owner:
+ repo_admin = is_repo_admin(username, old_repo_id)
+ if not repo_admin:
+ is_group_repo_admin = is_group_repo_staff(request, old_repo_id, username)
+
+ if not is_group_repo_admin:
+ error_msg = _('Permission denied.')
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if wiki.username != username:
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if not request.user.permissions.can_add_repo():
+ return api_error(status.HTTP_403_FORBIDDEN, 'You do not have permission to create library.')
+
+ wiki_name = request.data.get("name", None)
+ if not wiki_name:
+ return api_error(status.HTTP_400_BAD_REQUEST, 'wiki name is required.')
+
+ if not is_valid_wiki_name(wiki_name):
+ msg = _('Name can only contain letters, numbers, blank, hyphen or underscore.')
+ return api_error(status.HTTP_400_BAD_REQUEST, msg)
+
+ old_repo_id = wiki.repo_id
+ repo = seafile_api.get_repo(old_repo_id)
+ if not repo:
+ error_msg = 'Library %s not found.' % old_repo_id
+ return api_error(status.HTTP_404_NOT_FOUND, error_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)
+ wiki_owner = "%s@seafile_group" % group_id
+ 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, '', wiki_owner, org_id)
+ else:
+ repo_id = seafile_api.create_repo(wiki_name, '', wiki_owner)
+
+ try:
+ seafile_db_api = SeafileDB()
+ seafile_db_api.set_repo_type(repo_id, 'wiki')
+ except Exception as e:
+ logger.error(e)
+ msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, msg)
+
+ params = {
+ 'old_repo_id': old_repo_id,
+ 'new_repo_id': repo_id,
+ 'username': request.user.username,
+ }
+
+ try:
+ task_id = add_convert_wiki_task(params=params)
+ except Exception as e:
+ logger.error(e)
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')
+
+ return Response({"task_id": task_id})
+
diff --git a/seahub/urls.py b/seahub/urls.py
index 041e3615ce..6024273f4a 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -210,7 +210,7 @@ from seahub.ocm.settings import OCM_ENDPOINT
from seahub.wiki2.views import wiki_view, wiki_publish_view
from seahub.api2.endpoints.wiki2 import Wikis2View, Wiki2View, Wiki2ConfigView, Wiki2PagesView, Wiki2PageView, \
Wiki2DuplicatePageView, WikiPageTrashView, Wiki2PublishView, Wiki2PublishConfigView, Wiki2PublishPageView, \
- WikiSearch
+ WikiSearch, WikiConvertView
from seahub.api2.endpoints.subscription import SubscriptionView, SubscriptionPlansView, SubscriptionLogsView
from seahub.api2.endpoints.metadata_manage import MetadataRecords, MetadataManage, MetadataColumns, MetadataRecordInfo, \
MetadataViews, MetadataViewsMoveView, MetadataViewsDetailView, MetadataViewsDuplicateView, FacesRecords, \
@@ -558,7 +558,7 @@ urlpatterns = [
re_path(r'^api/v2.1/wiki2/(?P[-0-9a-f]{36})/trash/', WikiPageTrashView.as_view(), name='api-v2.1-wiki2-trash'),
re_path(r'^api/v2.1/wiki2/(?P[-0-9a-f]{36})/publish/$', Wiki2PublishView.as_view(), name='api-v2.1-wiki2-publish'),
re_path(r'^api/v2.1/wiki2/search/$', WikiSearch.as_view(), name='api-v2.1-wiki2-search'),
-
+ re_path(r'^api/v2.1/convert-wiki/$', WikiConvertView.as_view(), name='api-v2.1-wiki-convert'),
## user::drafts
re_path(r'^api/v2.1/drafts/$', DraftsView.as_view(), name='api-v2.1-drafts'),
re_path(r'^api/v2.1/drafts/(?P\d+)/$', DraftView.as_view(), name='api-v2.1-draft'),
@@ -801,7 +801,7 @@ urlpatterns = [
re_path(r'^api/v2.1/internal/user-list/$', InternalUserListView.as_view(), name="api-v2.1-internal-user-list"),
re_path(r'^api/v2.1/internal/check-share-link-access/$', InternalCheckShareLinkAccess.as_view(), name="api-v2.1-internal-share-link-info"),
re_path(r'^api/v2.1/internal/repos/(?P[-0-9a-f]{36})/check-access/$', InternalCheckFileOperationAccess.as_view(), name="api-v2.1-internal-check-file-op-access"),
-
+
### system admin ###
re_path(r'^sys/seafadmin/delete/(?P[-0-9a-f]{36})/$', sys_repo_delete, name='sys_repo_delete'),
path('sys/useradmin/export-excel/', sys_useradmin_export_excel, name='sys_useradmin_export_excel'),
@@ -956,8 +956,8 @@ if getattr(settings, 'ENABLE_KRB5_LOGIN', False):
urlpatterns += [
re_path(r'^krb5-login/', shib_login, name="krb5_login"),
]
-
-
+
+
if getattr(settings, 'ENABLE_LOGIN_SIMPLE_CHECK', False):
urlpatterns += [
re_path(r'^sso-auto-login/', login_simple_check),
diff --git a/seahub/wiki2/utils.py b/seahub/wiki2/utils.py
index ac3dc3ab4b..c39314567b 100644
--- a/seahub/wiki2/utils.py
+++ b/seahub/wiki2/utils.py
@@ -8,12 +8,16 @@ import json
import requests
import posixpath
import random
+import jwt
+import time
+from urllib.parse import urljoin
from seaserv import seafile_api
from seahub.constants import PERMISSION_READ_WRITE
from seahub.utils import gen_inner_file_get_url, gen_file_upload_url
from seahub.group.utils import is_group_admin, is_group_member
from seahub.wiki2.models import WikiPageTrash
+from seahub.settings import SECRET_KEY, SEAFEVENTS_SERVER_URL
logger = logging.getLogger(__name__)
@@ -271,7 +275,7 @@ def move_nav(navigation, target_id, moved_nav, move_position):
def revert_nav(navigation, parent_page_id, subpages):
-
+
# connect the subpages to the parent_page
# if not parent_page_id marked as flag, connect the subpages to the root
def recurse(navigation, parent_page_id, subpages):
@@ -318,3 +322,12 @@ def get_parent_id_stack(navigation, page_id):
return_parent_page_id(navigation, page_id, id_list)
return id_list
+
+
+def add_convert_wiki_task(params):
+ payload = {'exp': int(time.time()) + 300, }
+ token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
+ headers = {"Authorization": "Token %s" % token}
+ url = urljoin(SEAFEVENTS_SERVER_URL, '/add-convert-wiki-task')
+ resp = requests.get(url, params=params, headers=headers)
+ return json.loads(resp.content)['task_id']