1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-21 11:27:18 +00:00

copy_file_from_history (#5486)

* copy_file_from_history

* fix SeadocCopyHistoryFile
This commit is contained in:
欢乐马
2023-06-15 16:27:24 +08:00
committed by GitHub
parent 15dfbd6c17
commit fab9c039af
4 changed files with 91 additions and 2 deletions

View File

@@ -48,6 +48,11 @@ class HistoryVersion extends React.Component {
// nothing todo // nothing todo
} }
onItemCopy = () => {
const { historyVersion } = this.props;
this.props.onCopy(historyVersion);
}
render() { render() {
const { currentVersion, historyVersion } = this.props; const { currentVersion, historyVersion } = this.props;
if (!currentVersion || !historyVersion) return null; if (!currentVersion || !historyVersion) return null;
@@ -80,6 +85,7 @@ class HistoryVersion extends React.Component {
<DropdownMenu> <DropdownMenu>
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>} {(this.props.index !== 0) && <DropdownItem onClick={this.onItemRestore}>{gettext('Restore')}</DropdownItem>}
<DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem> <DropdownItem tag='a' href={url} onClick={this.onItemDownLoad}>{gettext('Download')}</DropdownItem>
{(this.props.index !== 0) && <DropdownItem onClick={this.onItemCopy}>{gettext('Copy')}</DropdownItem>}
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
</div> </div>
@@ -94,6 +100,7 @@ HistoryVersion.propTypes = {
historyVersion: PropTypes.object, historyVersion: PropTypes.object,
onSelectHistoryVersion: PropTypes.func.isRequired, onSelectHistoryVersion: PropTypes.func.isRequired,
onRestore: PropTypes.func.isRequired, onRestore: PropTypes.func.isRequired,
onCopy: PropTypes.func.isRequired,
}; };
export default HistoryVersion; export default HistoryVersion;

View File

@@ -115,6 +115,19 @@ class SidePanel extends Component {
this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]); this.props.onSelectHistoryVersion(historyVersion, historyVersions[historyVersionIndex + 1]);
} }
copyHistoryFile = (historyVersion) => {
const { path, revFileId, ctime } = historyVersion;
seafileAPI.sdocCopyHistoryFile(historyRepoID, path, revFileId, ctime).then(res => {
let message = gettext('Successfully copied %(name)s.');
let filename = res.data.file_name;
message = message.replace('%(name)s', filename);
toaster.success(message);
}).catch(error => {
const errorMessage = Utils.getErrorMsg(error, true);
toaster.danger(gettext(errorMessage));
});
}
renderHistoryVersions = () => { renderHistoryVersions = () => {
const { isLoading, historyVersions, errorMessage } = this.state; const { isLoading, historyVersions, errorMessage } = this.state;
if (historyVersions.length === 0) { if (historyVersions.length === 0) {
@@ -150,6 +163,7 @@ class SidePanel extends Component {
historyVersion={historyVersion} historyVersion={historyVersion}
onSelectHistoryVersion={this.onSelectHistoryVersion} onSelectHistoryVersion={this.onSelectHistoryVersion}
onRestore={this.restoreVersion} onRestore={this.restoreVersion}
onCopy={this.copyHistoryFile}
/> />
); );
})} })}

View File

@@ -1,4 +1,5 @@
import os import os
import json
import logging import logging
import requests import requests
import posixpath import posixpath
@@ -10,6 +11,7 @@ from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.http import HttpResponseRedirect, HttpResponse from django.http import HttpResponseRedirect, HttpResponse
from django.core.files.base import ContentFile
from seaserv import seafile_api, check_quota from seaserv import seafile_api, check_quota
@@ -22,9 +24,11 @@ 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, \ gen_seadoc_image_parent_path, get_seadoc_asset_upload_link, get_seadoc_asset_download_link, \
can_access_seadoc_asset can_access_seadoc_asset
from seahub.utils.file_types import SEADOC, IMAGE 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, \
gen_inner_file_get_url, gen_inner_file_upload_url
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap
from seahub.utils.error_msg import file_type_error_msg from seahub.utils.error_msg import file_type_error_msg
from seahub.utils.repo import parse_repo_perm
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -286,3 +290,66 @@ class SeadocDownloadImage(APIView):
filetype, fileext = get_file_type_and_ext(filename) filetype, fileext = get_file_type_and_ext(filename)
return HttpResponse( return HttpResponse(
content=resp.content, content_type='image/' + fileext) content=resp.content, content_type='image/' + fileext)
class SeadocCopyHistoryFile(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle, )
def post(self, request, repo_id):
username = request.user.username
obj_id = request.data.get('obj_id', '')
path = request.data.get('p', '')
ctime = request.data.get('ctime', '')
# only check the permissions at the repo level
# to prevent file can not be copied on the history page
if not parse_repo_perm(check_folder_permission(request, repo_id, '/')).can_copy:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# new file name
file_name = os.path.basename(path.rstrip('/'))
parent_dir = os.path.dirname(path)
new_file_name = '.'.join(file_name.split('.')[0:-1]) + \
'(' + str(ctime) + ').' + file_name.split('.')[-1]
new_file_path = posixpath.join(parent_dir, new_file_name)
# download
token = seafile_api.get_fileserver_access_token(repo_id,
obj_id, 'download', username)
if not token:
error_msg = 'file %s not found.' % obj_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
download_url = gen_inner_file_get_url(token, file_name)
resp = requests.get(download_url)
content = resp.content
file = ContentFile(content)
file.name = new_file_name
# upload
obj_id = json.dumps({'parent_dir': parent_dir})
token = seafile_api.get_fileserver_access_token(
repo_id, obj_id, 'upload-link', username, use_onetime=True)
if not token:
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
upload_link = gen_inner_file_upload_url('upload-api', token)
files = {
'file': file,
'file_name': new_file_name,
'target_file': new_file_path,
}
data = {'parent_dir': parent_dir}
resp = requests.post(upload_link, files=files, data=data)
if not resp.ok:
logger.error(resp.text)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({
'file_name': new_file_name,
'file_path': new_file_path,
})

View File

@@ -1,6 +1,6 @@
from django.urls import re_path from django.urls import re_path
from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, SeadocUploadFile, \ from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, SeadocUploadFile, \
SeadocUploadImage, SeadocDownloadImage SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile
urlpatterns = [ urlpatterns = [
re_path(r'^access-token/(?P<repo_id>[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'), re_path(r'^access-token/(?P<repo_id>[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'),
@@ -9,4 +9,5 @@ urlpatterns = [
re_path(r'^download-link/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocDownloadLink.as_view(), name='seadoc_download_link'), re_path(r'^download-link/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocDownloadLink.as_view(), name='seadoc_download_link'),
re_path(r'^upload-image/(?P<file_uuid>[-0-9a-f]{36})/$', SeadocUploadImage.as_view(), name='seadoc_upload_image'), 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'^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'),
] ]