1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-11 20:01:40 +00:00

clean invalid share/upload links (#5403)

* clean invalid share/upload links

* update
This commit is contained in:
lian 2023-03-17 09:44:20 +08:00 committed by GitHub
parent 1da123ee76
commit ac93d4e103
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 37 deletions

View File

@ -320,7 +320,7 @@ class ShareAdminShareLinks extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
isCleanOrphanShareLinksDialogOpen: false, isCleanInvalidShareLinksDialogOpen: false,
loading: true, loading: true,
errorMsg: '', errorMsg: '',
items: [], items: [],
@ -428,15 +428,15 @@ class ShareAdminShareLinks extends Component {
}); });
} }
toggleCleanOrphanShareLinksDialog = () => { toggleCleanInvalidShareLinksDialog = () => {
this.setState({isCleanOrphanShareLinksDialogOpen: !this.state.isCleanOrphanShareLinksDialogOpen}); this.setState({isCleanInvalidShareLinksDialogOpen: !this.state.isCleanInvalidShareLinksDialogOpen});
} }
cleanOrphanShareLinks = () => { cleanInvalidShareLinks = () => {
seafileAPI.cleanOrphanShareLinks().then(res => { seafileAPI.cleanInvalidShareLinks().then(res => {
const newItems = this.state.items.filter(item => item.obj_id !== ''); const newItems = this.state.items.filter(item => item.obj_id !== '').filter(item => !item.is_expired);
this.setState({items: newItems}); this.setState({items: newItems});
toaster.success(gettext('Successfully cleaned orphan share links.')); toaster.success(gettext('Successfully cleaned invalid share links.'));
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage); toaster.danger(errMessage);
@ -451,7 +451,7 @@ class ShareAdminShareLinks extends Component {
onSearchedClick={this.props.onSearchedClick} onSearchedClick={this.props.onSearchedClick}
> >
<Button className="operation-item d-none d-md-block" onClick={this.toggleCleanOrphanShareLinksDialog}>{gettext('Clean orphan share links')}</Button> <Button className="operation-item d-none d-md-block" onClick={this.toggleCleanInvalidShareLinksDialog}>{gettext('Clean invalid share links')}</Button>
</TopToolbar> </TopToolbar>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
@ -488,13 +488,13 @@ class ShareAdminShareLinks extends Component {
sortItems={this.sortItems} sortItems={this.sortItems}
/> />
} }
{this.state.isCleanOrphanShareLinksDialogOpen && {this.state.isCleanInvalidShareLinksDialogOpen &&
<CommonOperationConfirmationDialog <CommonOperationConfirmationDialog
title={gettext('Clean orphan share links')} title={gettext('Clean invalid share links')}
message={gettext('Are you sure you want to clean orphan share links?')} message={gettext('Are you sure you want to clean invalid share links?')}
executeOperation={this.cleanOrphanShareLinks} executeOperation={this.cleanInvalidShareLinks}
confirmBtnText={gettext('Clean')} confirmBtnText={gettext('Clean')}
toggleDialog={this.toggleCleanOrphanShareLinksDialog} toggleDialog={this.toggleCleanInvalidShareLinksDialog}
/> />
} }
</Fragment> </Fragment>

View File

@ -211,7 +211,7 @@ class ShareAdminUploadLinks extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
isCleanOrphanUploadLinksDialogOpen: false, isCleanInvalidUploadLinksDialogOpen: false,
loading: true, loading: true,
errorMsg: '', errorMsg: '',
items: [] items: []
@ -253,15 +253,15 @@ class ShareAdminUploadLinks extends Component {
}); });
} }
toggleCleanOrphanUploadLinksDialog = () => { toggleCleanInvalidUploadLinksDialog = () => {
this.setState({isCleanOrphanUploadLinksDialogOpen: !this.state.isCleanOrphanUploadLinksDialogOpen}); this.setState({isCleanInvalidUploadLinksDialogOpen: !this.state.isCleanInvalidUploadLinksDialogOpen});
} }
cleanOrphanUploadLinks = () => { cleanInvalidUploadLinks = () => {
seafileAPI.cleanOrphanUploadLinks().then(res => { seafileAPI.cleanInvalidUploadLinks().then(res => {
const newItems = this.state.items.filter(item => item.obj_id !== ''); const newItems = this.state.items.filter(item => item.obj_id !== '').filter(item => !item.is_expired);
this.setState({items: newItems}); this.setState({items: newItems});
toaster.success(gettext('Successfully cleaned orphan upload links.')); toaster.success(gettext('Successfully cleaned invalid upload links.'));
}).catch(error => { }).catch(error => {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage); toaster.danger(errMessage);
@ -275,7 +275,7 @@ class ShareAdminUploadLinks extends Component {
onShowSidePanel={this.props.onShowSidePanel} onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick} onSearchedClick={this.props.onSearchedClick}
> >
<Button className="operation-item d-none d-md-block" onClick={this.toggleCleanOrphanUploadLinksDialog}>{gettext('Clean orphan upload links')}</Button> <Button className="operation-item d-none d-md-block" onClick={this.toggleCleanInvalidUploadLinksDialog}>{gettext('Clean invalid upload links')}</Button>
</TopToolbar> </TopToolbar>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
@ -297,13 +297,13 @@ class ShareAdminUploadLinks extends Component {
</div> </div>
</div> </div>
</div> </div>
{this.state.isCleanOrphanUploadLinksDialogOpen && {this.state.isCleanInvalidUploadLinksDialogOpen &&
<CommonOperationConfirmationDialog <CommonOperationConfirmationDialog
title={gettext('Clean orphan upload links')} title={gettext('Clean invalid upload links')}
message={gettext('Are you sure you want to clean orphan upload links?')} message={gettext('Are you sure you want to clean invalid upload links?')}
executeOperation={this.cleanOrphanUploadLinks} executeOperation={this.cleanInvalidUploadLinks}
confirmBtnText={gettext('Clean')} confirmBtnText={gettext('Clean')}
toggleDialog={this.toggleCleanOrphanUploadLinksDialog} toggleDialog={this.toggleCleanInvalidUploadLinksDialog}
/> />
} }
</Fragment> </Fragment>

View File

@ -1209,7 +1209,7 @@ class ShareLinkSaveItemsToRepo(APIView):
src_parent_dir = os.path.dirname(src_dirent_path) src_parent_dir = os.path.dirname(src_dirent_path)
src_dirent_name = os.path.basename(src_dirent_path) src_dirent_name = os.path.basename(src_dirent_path)
dst_dirent_name = check_filename_with_rename(dst_repo_id, check_filename_with_rename(dst_repo_id,
dst_parent_dir, dst_parent_dir,
src_dirent_name) src_dirent_name)
else: else:
@ -1337,14 +1337,14 @@ class ShareLinkRepoTagsTaggedFiles(APIView):
return Response({'tagged_files': filtered_tagged_files}) return Response({'tagged_files': filtered_tagged_files})
class ShareLinksCleanOrphan(APIView): class ShareLinksCleanInvalid(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication) authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, CanGenerateShareLink) permission_classes = (IsAuthenticated, CanGenerateShareLink)
throttle_classes = (UserRateThrottle,) throttle_classes = (UserRateThrottle,)
def delete(self, request): def delete(self, request):
""" Clean orphan share links. """ Clean invalid share links.
""" """
username = request.user.username username = request.user.username
@ -1352,6 +1352,10 @@ class ShareLinksCleanOrphan(APIView):
for share_link in share_links: for share_link in share_links:
if share_link.is_expired():
share_link.delete()
continue
repo_id = share_link.repo_id repo_id = share_link.repo_id
if not seafile_api.get_repo(repo_id): if not seafile_api.get_repo(repo_id):
share_link.delete() share_link.delete()

View File

@ -481,13 +481,13 @@ class UploadLinkUpload(APIView):
return Response(result) return Response(result)
class UploadLinksCleanOrphan(APIView): class UploadLinksCleanInvalid(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication) authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, CanGenerateUploadLink) permission_classes = (IsAuthenticated, CanGenerateUploadLink)
throttle_classes = (UserRateThrottle, ) throttle_classes = (UserRateThrottle, )
def delete(self, request): def delete(self, request):
""" Clean orphan upload links. """ Clean invalid upload links.
""" """
username = request.user.username username = request.user.username
@ -495,6 +495,10 @@ class UploadLinksCleanOrphan(APIView):
for upload_link in upload_links: for upload_link in upload_links:
if upload_link.is_expired():
upload_link.delete()
continue
repo_id = upload_link.repo_id repo_id = upload_link.repo_id
if not seafile_api.get_repo(repo_id): if not seafile_api.get_repo(repo_id):
upload_link.delete() upload_link.delete()

View File

@ -41,11 +41,11 @@ from seahub.api2.endpoints.search_group import SearchGroup
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink, \ from seahub.api2.endpoints.share_links import ShareLinks, ShareLink, \
ShareLinkOnlineOfficeLock, ShareLinkDirents, ShareLinkSaveFileToRepo, \ ShareLinkOnlineOfficeLock, ShareLinkDirents, ShareLinkSaveFileToRepo, \
ShareLinkUpload, ShareLinkUploadDone, ShareLinkSaveItemsToRepo, \ ShareLinkUpload, ShareLinkUploadDone, ShareLinkSaveItemsToRepo, \
ShareLinkRepoTags, ShareLinkRepoTagsTaggedFiles, ShareLinksCleanOrphan ShareLinkRepoTags, ShareLinkRepoTagsTaggedFiles, ShareLinksCleanInvalid
from seahub.api2.endpoints.shared_folders import SharedFolders from seahub.api2.endpoints.shared_folders import SharedFolders
from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \ from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
UploadLinkUpload, UploadLinksCleanOrphan UploadLinkUpload, UploadLinksCleanInvalid
from seahub.api2.endpoints.repos_batch import ReposBatchView, \ from seahub.api2.endpoints.repos_batch import ReposBatchView, \
ReposBatchCopyDirView, ReposBatchCreateDirView, \ ReposBatchCopyDirView, ReposBatchCreateDirView, \
ReposBatchCopyItemView, ReposBatchMoveItemView, \ ReposBatchCopyItemView, ReposBatchMoveItemView, \
@ -344,7 +344,7 @@ urlpatterns = [
## user::shared-download-links ## user::shared-download-links
url(r'^api/v2.1/share-links/$', ShareLinks.as_view(), name='api-v2.1-share-links'), url(r'^api/v2.1/share-links/$', ShareLinks.as_view(), name='api-v2.1-share-links'),
url(r'^api/v2.1/share-links/clean-orphan/$', ShareLinksCleanOrphan.as_view(), name='api-v2.1-share-links-clean-orphan'), url(r'^api/v2.1/share-links/clean-invalid/$', ShareLinksCleanInvalid.as_view(), name='api-v2.1-share-links-clean-invalid'),
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/$', ShareLink.as_view(), name='api-v2.1-share-link'), url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/$', ShareLink.as_view(), name='api-v2.1-share-link'),
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/save-file-to-repo/$', ShareLinkSaveFileToRepo.as_view(), name='api-v2.1-share-link-save-file-to-repo'), url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/save-file-to-repo/$', ShareLinkSaveFileToRepo.as_view(), name='api-v2.1-share-link-save-file-to-repo'),
url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/save-items-to-repo/$', ShareLinkSaveItemsToRepo.as_view(), name='api-v2.1-share-link-save-items-to-repo'), url(r'^api/v2.1/share-links/(?P<token>[a-f0-9]+)/save-items-to-repo/$', ShareLinkSaveItemsToRepo.as_view(), name='api-v2.1-share-link-save-items-to-repo'),
@ -359,7 +359,7 @@ urlpatterns = [
## user::shared-upload-links ## user::shared-upload-links
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'), url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
url(r'^api/v2.1/upload-links/clean-orphan/$', UploadLinksCleanOrphan.as_view(), name='api-v2.1-upload-links-clean-orphan'), url(r'^api/v2.1/upload-links/clean-invalid/$', UploadLinksCleanInvalid.as_view(), name='api-v2.1-upload-links-clean-invalid'),
url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/$', UploadLink.as_view(), name='api-v2.1-upload-link'), url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/upload/$', UploadLinkUpload.as_view(), name='api-v2.1-upload-link-upload'), url(r'^api/v2.1/upload-links/(?P<token>[a-f0-9]+)/upload/$', UploadLinkUpload.as_view(), name='api-v2.1-upload-link-upload'),