mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-26 15:26:19 +00:00
renameSdocHistory (#5500)
* renameSdocHistory * sdoc NewFileHistoryView * add SeadocHistoryName
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap';
|
||||
import { gettext, filePath } from '../../utils/constants';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
import Rename from '../../components/rename';
|
||||
|
||||
import '../../css/history-record-item.css';
|
||||
|
||||
moment.locale(window.app.config.lang);
|
||||
|
||||
class HistoryVersion extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -13,18 +17,19 @@ class HistoryVersion extends React.Component {
|
||||
this.state = {
|
||||
isShowOperationIcon: false,
|
||||
isMenuShow: false,
|
||||
isRenameShow: false,
|
||||
};
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
if (currentVersion.commitId === historyVersion.commitId) return;
|
||||
if (currentVersion.commit_id === historyVersion.commit_id) return;
|
||||
this.setState({ isShowOperationIcon: true });
|
||||
}
|
||||
|
||||
onMouseLeave = () => {
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
if (currentVersion.commitId === historyVersion.commitId) return;
|
||||
if (currentVersion.commit_id === historyVersion.commit_id) return;
|
||||
this.setState({ isShowOperationIcon: false });
|
||||
}
|
||||
|
||||
@@ -35,7 +40,7 @@ class HistoryVersion extends React.Component {
|
||||
onClick = () => {
|
||||
this.setState({ isShowOperationIcon: false });
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
if (currentVersion.commitId === historyVersion.commitId) return;
|
||||
if (currentVersion.commit_id === historyVersion.commit_id) return;
|
||||
this.props.onSelectHistoryVersion(historyVersion);
|
||||
}
|
||||
|
||||
@@ -50,15 +55,30 @@ class HistoryVersion extends React.Component {
|
||||
|
||||
onItemCopy = () => {
|
||||
const { historyVersion } = this.props;
|
||||
historyVersion.ctime_format = moment(historyVersion.ctime).format('YYYY-MM-DD HH:mm');
|
||||
this.props.onCopy(historyVersion);
|
||||
}
|
||||
|
||||
toggleRename = () => {
|
||||
this.setState({isRenameShow: !this.state.isRenameShow});
|
||||
}
|
||||
|
||||
onRenameConfirm = (newName) => {
|
||||
const { obj_id } = this.props.historyVersion;
|
||||
this.props.renameHistoryVersion(obj_id, newName);
|
||||
this.toggleRename();
|
||||
}
|
||||
|
||||
onRenameCancel = () => {
|
||||
this.toggleRename();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentVersion, historyVersion } = this.props;
|
||||
if (!currentVersion || !historyVersion) return null;
|
||||
const { ctime, commitId, creatorName, revFileId } = historyVersion;
|
||||
const isHighlightItem = commitId === currentVersion.commitId;
|
||||
const url = URLDecorator.getUrl({ type: 'download_historic_file', filePath: filePath, objID: revFileId });
|
||||
const { ctime, commit_id, creator_name, obj_id, name} = historyVersion;
|
||||
const isHighlightItem = commit_id === currentVersion.commit_id;
|
||||
const url = URLDecorator.getUrl({ type: 'download_historic_file', filePath: filePath, objID: obj_id });
|
||||
return (
|
||||
<li
|
||||
className={`history-list-item ${isHighlightItem ? 'item-active' : ''}`}
|
||||
@@ -67,10 +87,14 @@ class HistoryVersion extends React.Component {
|
||||
onClick={this.onClick}
|
||||
>
|
||||
<div className="history-info">
|
||||
<div className="time">{ctime}</div>
|
||||
{this.state.isRenameShow ?
|
||||
<Rename name={name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/>
|
||||
:<div className="name">{name}</div>
|
||||
}
|
||||
<div className="time">{moment(ctime).format('YYYY-MM-DD HH:mm')}</div>
|
||||
<div className="owner">
|
||||
<span className="squire-icon"></span>
|
||||
<span>{creatorName}</span>
|
||||
<span>{creator_name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="history-operation">
|
||||
@@ -86,6 +110,7 @@ class HistoryVersion extends React.Component {
|
||||
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>}
|
||||
<DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem>
|
||||
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>}
|
||||
<DropdownItem onClick={this.toggleRename}>{gettext('Rename')}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
@@ -101,6 +126,7 @@ HistoryVersion.propTypes = {
|
||||
onSelectHistoryVersion: PropTypes.func.isRequired,
|
||||
onRestore: PropTypes.func.isRequired,
|
||||
onCopy: PropTypes.func.isRequired,
|
||||
renameHistoryVersion: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default HistoryVersion;
|
||||
|
@@ -50,12 +50,12 @@ class SdocFileHistory extends React.Component {
|
||||
|
||||
onSelectHistoryVersion = (currentVersion, lastVersion) => {
|
||||
this.setState({ isLoading: true, currentVersion });
|
||||
seafileAPI.getFileRevision(historyRepoID, currentVersion.commitId, currentVersion.path).then(res => {
|
||||
seafileAPI.getFileRevision(historyRepoID, currentVersion.commit_id, currentVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
}).then(res => {
|
||||
const currentVersionContent = res.data;
|
||||
if (lastVersion) {
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commitId, lastVersion.path).then(res => {
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
}).then(res => {
|
||||
const lastVersionContent = res.data;
|
||||
@@ -84,7 +84,7 @@ class SdocFileHistory extends React.Component {
|
||||
const { currentVersionContent } = this.state;
|
||||
this.setState({ isLoading: true }, () => {
|
||||
localStorage.setItem('seahub-sdoc-history-show-changes', isShowChanges + '');
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commitId, lastVersion.path).then(res => {
|
||||
seafileAPI.getFileRevision(historyRepoID, lastVersion.commit_id, lastVersion.path).then(res => {
|
||||
return seafileAPI.getFileContent(res.data);
|
||||
}).then(res => {
|
||||
const lastVersionContent = res.data;
|
||||
|
@@ -2,15 +2,16 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Loading from '../../components/loading';
|
||||
import { gettext, filePath, historyRepoID } from '../../utils/constants';
|
||||
import { gettext, historyRepoID, PER_PAGE } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import FileHistory from '../../models/file-history';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import editUtilities from '../../utils/editor-utilities';
|
||||
import toaster from '../../components/toast';
|
||||
import HistoryVersion from './history-version';
|
||||
import Switch from '../../components/common/switch';
|
||||
|
||||
const { docUuid } = window.fileHistory.pageOptions;
|
||||
|
||||
class SidePanel extends Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -19,85 +20,104 @@ class SidePanel extends Component {
|
||||
isLoading: true,
|
||||
historyVersions: [],
|
||||
errorMessage: '',
|
||||
currentPage: 1,
|
||||
hasMore: false,
|
||||
fileOwner: '',
|
||||
isReloadingData: false,
|
||||
};
|
||||
this.init();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listHistoryVersions(historyRepoID, filePath, this.nextCommit, (historyVersion, lastHistoryVersion) => {
|
||||
this.props.onSelectHistoryVersion(historyVersion, lastHistoryVersion);
|
||||
seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
|
||||
let historyList = res.data;
|
||||
if (historyList.length === 0) {
|
||||
this.setState({isLoading: false});
|
||||
throw Error('there has an error in server');
|
||||
}
|
||||
this.initResultState(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
init = () => {
|
||||
this.hasMore = true;
|
||||
this.nextCommit = '';
|
||||
this.filePath = '';
|
||||
this.oldFilePath = '';
|
||||
refershFileList() {
|
||||
seafileAPI.listSdocHistory(docUuid, 1, PER_PAGE).then(res => {
|
||||
this.initResultState(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
listHistoryVersions = (repoID, filePath, commit, callback) => {
|
||||
seafileAPI.listOldFileHistoryRecords(repoID, filePath, commit).then((res) => {
|
||||
let historyData = res.data;
|
||||
if (!historyData) {
|
||||
this.setState({ isLoading: false, errorMessage: 'There is an error in server.' });
|
||||
return;
|
||||
}
|
||||
this.updateHistoryVersions(historyData, callback);
|
||||
initResultState(result) {
|
||||
if (result.histories.length) {
|
||||
this.setState({
|
||||
historyVersions: result.histories,
|
||||
currentPage: result.page,
|
||||
hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
|
||||
isLoading: false,
|
||||
fileOwner: result.histories[0].creator_email,
|
||||
});
|
||||
this.props.onSelectHistoryVersion(result.histories[0], result.histories[1]);
|
||||
}
|
||||
}
|
||||
|
||||
updateResultState(result) {
|
||||
if (result.histories.length) {
|
||||
this.setState({
|
||||
historyVersions: [...this.state.historyVersions, ...result.histories],
|
||||
currentPage: result.page,
|
||||
hasMore: result.total_count > (PER_PAGE * this.state.currentPage),
|
||||
isLoading: false,
|
||||
fileOwner: result.histories[0].creator_email
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
if (!this.state.isReloadingData) {
|
||||
let currentPage = this.state.currentPage + 1;
|
||||
this.setState({
|
||||
currentPage: currentPage,
|
||||
isReloadingData: true,
|
||||
});
|
||||
seafileAPI.listSdocHistory(docUuid, currentPage, PER_PAGE).then(res => {
|
||||
this.updateResultState(res.data);
|
||||
this.setState({isReloadingData: false});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renameHistoryVersion = (objID, newName) => {
|
||||
seafileAPI.renameSdocHistory(docUuid, objID, newName).then((res) => {
|
||||
this.setState({
|
||||
historyVersions: this.state.historyVersions.map(item => {
|
||||
if (item.obj_id == objID) {
|
||||
item.name = newName;
|
||||
}
|
||||
return item;
|
||||
})
|
||||
});
|
||||
}).catch(error => {
|
||||
const errorMessage = Utils.getErrorMsg(error, true);
|
||||
this.setState({ isLoading: false, errorMessage: errorMessage });
|
||||
});
|
||||
}
|
||||
|
||||
updateHistoryVersions(result, callback) {
|
||||
const dataCount = result.data ? result.data.length : 0;
|
||||
this.nextCommit = result.next_start_commit || '';
|
||||
if (dataCount) {
|
||||
const addedHistoryVersions = result.data.map(item => new FileHistory(item));
|
||||
this.filePath = addedHistoryVersions[dataCount - 1].path;
|
||||
this.oldFilePath = addedHistoryVersions[dataCount - 1].revRenamedOldPath;
|
||||
const historyVersions = [ ...this.state.historyVersions, ...addedHistoryVersions ];
|
||||
this.setState({ historyVersions: historyVersions, isLoading: false, errorMessage: '' }, () => {
|
||||
callback && callback(historyVersions[0], historyVersions[1]);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.nextCommit) {
|
||||
this.listHistoryVersions(historyRepoID, filePath, this.nextCommit);
|
||||
return;
|
||||
}
|
||||
this.hasMore = false;
|
||||
this.setState({ isLoading: false, errorMessage: '' });
|
||||
}
|
||||
|
||||
onScrollHandler = (event) => {
|
||||
const clientHeight = event.target.clientHeight;
|
||||
const scrollHeight = event.target.scrollHeight;
|
||||
const scrollTop = event.target.scrollTop;
|
||||
const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight);
|
||||
if (isBottom && this.hasMore && this.nextCommit) {
|
||||
if (isBottom && this.state.hasMore) {
|
||||
this.loadMore();
|
||||
}
|
||||
}
|
||||
|
||||
loadMore = () => {
|
||||
if (this.state.isLoading) return;
|
||||
this.setState({ isLoading: true }, () => {
|
||||
const currentFilePath = this.oldFilePath || this.filePath;
|
||||
this.listHistoryVersions(historyRepoID, currentFilePath, this.nextCommit);
|
||||
});
|
||||
}
|
||||
|
||||
restoreVersion = (historyVersion) => {
|
||||
const { commitId, path } = historyVersion;
|
||||
editUtilities.revertFile(path, commitId).then(res => {
|
||||
restoreVersion = (currentItem) => {
|
||||
const { commit_id, path } = currentItem;
|
||||
editUtilities.revertFile(path, commit_id).then(res => {
|
||||
if (res.data.success) {
|
||||
this.init();
|
||||
this.setState({ isLoading: true, historyVersions: [], errorMessage: '' } , () => {
|
||||
this.listHistoryVersions(historyRepoID, filePath);
|
||||
});
|
||||
this.setState({isLoading: true});
|
||||
this.refershFileList();
|
||||
}
|
||||
let message = gettext('Successfully restored.');
|
||||
toaster.success(message);
|
||||
}).catch(error => {
|
||||
const errorMessage = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(gettext(errorMessage));
|
||||
@@ -111,13 +131,13 @@ class SidePanel extends Component {
|
||||
return;
|
||||
}
|
||||
const { historyVersions } = this.state;
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commitId === historyVersion.commitId);
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === historyVersion.commit_id);
|
||||
this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]);
|
||||
}
|
||||
|
||||
copyHistoryFile = (historyVersion) => {
|
||||
const { path, revFileId, ctime } = historyVersion;
|
||||
seafileAPI.sdocCopyHistoryFile(historyRepoID, path, revFileId, ctime).then(res => {
|
||||
const { path, obj_id, ctime_format } = historyVersion;
|
||||
seafileAPI.sdocCopyHistoryFile(historyRepoID, path, obj_id, ctime_format).then(res => {
|
||||
let message = gettext('Successfully copied %(name)s.');
|
||||
let filename = res.data.file_name;
|
||||
message = message.replace('%(name)s', filename);
|
||||
@@ -157,13 +177,14 @@ class SidePanel extends Component {
|
||||
{historyVersions.map((historyVersion, index) => {
|
||||
return (
|
||||
<HistoryVersion
|
||||
key={historyVersion.commitId}
|
||||
key={historyVersion.commit_id}
|
||||
index={index}
|
||||
currentVersion={this.props.currentVersion}
|
||||
historyVersion={historyVersion}
|
||||
onSelectHistoryVersion={this.onSelectHistoryVersion}
|
||||
onRestore={this.restoreVersion}
|
||||
onCopy={this.copyHistoryFile}
|
||||
renameHistoryVersion={this.renameHistoryVersion}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -179,7 +200,7 @@ class SidePanel extends Component {
|
||||
onShowChanges = () => {
|
||||
const { isShowChanges, currentVersion } = this.props;
|
||||
const { historyVersions } = this.state;
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commitId === currentVersion.commitId);
|
||||
const historyVersionIndex = historyVersions.findIndex(item => item.commit_id === currentVersion.commit_id);
|
||||
const lastVersion = historyVersions[historyVersionIndex + 1];
|
||||
this.props.onShowChanges(!isShowChanges, lastVersion);
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ import json
|
||||
import logging
|
||||
import requests
|
||||
import posixpath
|
||||
from datetime import datetime
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
@@ -24,11 +25,17 @@ from seahub.seadoc.utils import is_valid_seadoc_access_token, get_seadoc_upload_
|
||||
gen_seadoc_image_parent_path, get_seadoc_asset_upload_link, get_seadoc_asset_download_link, \
|
||||
can_access_seadoc_asset
|
||||
from seahub.utils.file_types import SEADOC, IMAGE
|
||||
from seahub.utils import get_file_type_and_ext, normalize_file_path, PREVIEW_FILEEXT, \
|
||||
from seahub.utils import get_file_type_and_ext, normalize_file_path, PREVIEW_FILEEXT, get_file_history, \
|
||||
gen_inner_file_get_url, gen_inner_file_upload_url
|
||||
from seahub.tags.models import FileUUIDMap
|
||||
from seahub.utils.error_msg import file_type_error_msg
|
||||
from seahub.utils.repo import parse_repo_perm
|
||||
from seahub.utils.file_revisions import get_file_revisions_within_limit
|
||||
from seahub.seadoc.models import SeadocHistoryName
|
||||
from seahub.avatar.templatetags.avatar_tags import api_avatar_url
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, \
|
||||
email2contact_email
|
||||
from seahub.utils.timeutils import utc_datetime_to_isoformat_timestr, timestamp_to_isoformat_timestr
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -353,3 +360,147 @@ class SeadocCopyHistoryFile(APIView):
|
||||
'file_name': new_file_name,
|
||||
'file_path': new_file_path,
|
||||
})
|
||||
|
||||
|
||||
class SeadocHistory(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def _get_new_file_history_info(self, ent, avatar_size, name_dict):
|
||||
info = {}
|
||||
creator_name = ent.op_user
|
||||
url, is_default, date_uploaded = api_avatar_url(creator_name, avatar_size)
|
||||
info['creator_avatar_url'] = url
|
||||
info['creator_email'] = creator_name
|
||||
info['creator_name'] = email2nickname(creator_name)
|
||||
info['creator_contact_email'] = email2contact_email(creator_name)
|
||||
info['ctime'] = utc_datetime_to_isoformat_timestr(ent.timestamp)
|
||||
info['size'] = ent.size
|
||||
info['obj_id'] = ent.file_id
|
||||
info['commit_id'] = ent.commit_id
|
||||
info['old_path'] = ent.old_path if hasattr(ent, 'old_path') else ''
|
||||
info['path'] = ent.path
|
||||
info['name'] = name_dict.get(ent.file_id, '')
|
||||
return info
|
||||
|
||||
def get(self, request, file_uuid):
|
||||
"""list history, same as NewFileHistoryView
|
||||
"""
|
||||
uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
|
||||
if not uuid_map:
|
||||
error_msg = 'seadoc uuid %s not found.' % file_uuid
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = uuid_map.repo_id
|
||||
username = request.user.username
|
||||
path = posixpath.join(uuid_map.parent_path, uuid_map.filename)
|
||||
|
||||
# permission check
|
||||
if not check_folder_permission(request, repo_id, path):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# 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)
|
||||
commit_id = repo.head_cmmt_id
|
||||
|
||||
try:
|
||||
avatar_size = int(request.GET.get('avatar_size', 32))
|
||||
page = int(request.GET.get('page', 1))
|
||||
per_page = int(request.GET.get('per_page', 25))
|
||||
except ValueError:
|
||||
avatar_size = 32
|
||||
page = 1
|
||||
per_page = 25
|
||||
|
||||
# Don't use seafile_api.get_file_id_by_path()
|
||||
# if path parameter is `rev_renamed_old_path`.
|
||||
# seafile_api.get_file_id_by_path() will return None.
|
||||
file_id = seafile_api.get_file_id_by_commit_and_path(repo_id,
|
||||
commit_id, path)
|
||||
if not file_id:
|
||||
error_msg = 'File %s not found.' % path
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# get repo history limit
|
||||
try:
|
||||
history_limit = seafile_api.get_repo_history_limit(repo_id)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
start = (page - 1) * per_page
|
||||
count = per_page
|
||||
try:
|
||||
file_revisions, total_count = get_file_history(repo_id, path, start, count, history_limit)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
name_dict = {}
|
||||
obj_id_list = [commit.file_id for commit in file_revisions]
|
||||
if obj_id_list:
|
||||
name_queryset = SeadocHistoryName.objects.list_by_obj_ids(
|
||||
doc_uuid=file_uuid, obj_id_list=obj_id_list)
|
||||
name_dict = {item.obj_id: item.name for item in name_queryset}
|
||||
data = [self._get_new_file_history_info(ent, avatar_size, name_dict) for ent in file_revisions]
|
||||
result = {
|
||||
"histories": data,
|
||||
"page": page,
|
||||
"total_count": total_count
|
||||
}
|
||||
return Response(result)
|
||||
|
||||
def post(self, request, file_uuid):
|
||||
"""rename history
|
||||
"""
|
||||
username = request.user.username
|
||||
obj_id = request.data.get('obj_id', '')
|
||||
new_name = request.data.get('new_name', '')
|
||||
if not obj_id:
|
||||
error_msg = 'obj_id invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
if not new_name:
|
||||
error_msg = 'new_name invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
|
||||
if not uuid_map:
|
||||
error_msg = 'seadoc uuid %s not found.' % file_uuid
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = uuid_map.repo_id
|
||||
username = request.user.username
|
||||
path = posixpath.join(uuid_map.parent_path, uuid_map.filename)
|
||||
|
||||
# permission check
|
||||
if not check_folder_permission(request, repo_id, path):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# 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)
|
||||
|
||||
token = seafile_api.get_fileserver_access_token(repo_id,
|
||||
obj_id, 'download', username)
|
||||
if not token:
|
||||
error_msg = 'history %s not found.' % obj_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# main
|
||||
SeadocHistoryName.objects.update_name(file_uuid, obj_id, new_name)
|
||||
|
||||
return Response({
|
||||
'obj_id': obj_id,
|
||||
'name': new_name,
|
||||
})
|
||||
|
33
seahub/seadoc/models.py
Normal file
33
seahub/seadoc/models.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class SeadocHistoryNameManager(models.Manager):
|
||||
def update_name(self, doc_uuid, obj_id, name):
|
||||
if self.filter(doc_uuid=doc_uuid, obj_id=obj_id).exists():
|
||||
obj = self.filter(doc_uuid=doc_uuid, obj_id=obj_id).update(name=name)
|
||||
else:
|
||||
obj = self.create(doc_uuid=doc_uuid, obj_id=obj_id, name=name)
|
||||
return obj
|
||||
|
||||
def list_by_obj_ids(self, doc_uuid, obj_id_list):
|
||||
return self.filter(doc_uuid=doc_uuid, obj_id__in=obj_id_list)
|
||||
|
||||
|
||||
class SeadocHistoryName(models.Model):
|
||||
doc_uuid = models.CharField(max_length=36, db_index=True)
|
||||
obj_id = models.CharField(max_length=40)
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
objects = SeadocHistoryNameManager()
|
||||
|
||||
class Meta:
|
||||
db_table = 'history_name'
|
||||
unique_together = ('doc_uuid', 'obj_id')
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.pk,
|
||||
'doc_uuid': self.doc_uuid,
|
||||
'obj_id': self.obj_id,
|
||||
'name': self.name,
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
from django.urls import re_path
|
||||
from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, SeadocUploadFile, \
|
||||
SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile
|
||||
SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile, SeadocHistory
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r'^access-token/(?P<repo_id>[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'),
|
||||
@@ -10,4 +10,5 @@ urlpatterns = [
|
||||
re_path(r'^upload-image/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocUploadImage.as_view(), name='seadoc_upload_image'),
|
||||
re_path(r'^download-image/(?P<file_uuid>[-0-9a-f]{36})/(?P<filename>.*)$', SeadocDownloadImage.as_view(), name='seadoc_download_image'),
|
||||
re_path(r'^copy-history-file/(?P<repo_id>[-0-9a-f]{36})/$', SeadocCopyHistoryFile.as_view(), name='seadoc_copy_history_file'),
|
||||
re_path(r'^history/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocHistory.as_view(), name='seadoc_history'),
|
||||
]
|
||||
|
@@ -275,6 +275,7 @@ INSTALLED_APPS = [
|
||||
'seahub.organizations',
|
||||
'seahub.krb5_auth',
|
||||
'seahub.django_cas_ng',
|
||||
'seahub.seadoc',
|
||||
]
|
||||
|
||||
|
||||
|
@@ -1375,3 +1375,13 @@ CREATE TABLE `organizations_orgadminsettings` (
|
||||
UNIQUE KEY `organizations_orgadminsettings_org_id_key_a01cc7de_uniq` (`org_id`,`key`),
|
||||
KEY `organizations_orgadminsettings_org_id_4f70d186` (`org_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `history_name` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`doc_uuid` varchar(36) NOT NULL,
|
||||
`obj_id` varchar(40) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `history_name_doc_uuid` (`doc_uuid`),
|
||||
UNIQUE KEY `history_name_doc_uuid_obj_id` (`doc_uuid`, `obj_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
Reference in New Issue
Block a user