diff --git a/frontend/src/pages/upload-link/index.js b/frontend/src/pages/upload-link/index.js
index 7e5e178e44..932e3a0e2f 100644
--- a/frontend/src/pages/upload-link/index.js
+++ b/frontend/src/pages/upload-link/index.js
@@ -1,6 +1,7 @@
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';
import { Utils } from '../../utils/utils';
+import { seafileAPI } from '../../utils/seafile-api';
import { gettext } from '../../utils/constants';
import Logo from '../../components/logo';
import Account from '../../components/common/account';
@@ -22,6 +23,11 @@ const {
class SharedUploadLink extends React.Component {
+ onFileUploadSuccess = (direntObject) => {
+ const { name, size } = direntObject;
+ seafileAPI.shareLinksUploadDone(token, Utils.joinPath(path, name));
+ }
+
render() {
return (
@@ -55,7 +61,7 @@ class SharedUploadLink extends React.Component {
token={token}
repoID={repoID}
path={path}
- onFileUploadSuccess={() => {}}
+ onFileUploadSuccess={this.onFileUploadSuccess}
/>
)}
diff --git a/frontend/src/shared-dir-view.js b/frontend/src/shared-dir-view.js
index 8201ab2877..648b3b9559 100644
--- a/frontend/src/shared-dir-view.js
+++ b/frontend/src/shared-dir-view.js
@@ -262,6 +262,7 @@ class SharedDirView extends React.Component {
let items = Array.from(this.state.items);
items.splice(folderItems.length, 0, newItem);
this.setState({items: items});
+ seafileAPI.shareLinksUploadDone(token, Utils.joinPath(dirPath, name));
}
render() {
diff --git a/seahub/api2/endpoints/share_links.py b/seahub/api2/endpoints/share_links.py
index df4bfb6faf..77a59eb307 100644
--- a/seahub/api2/endpoints/share_links.py
+++ b/seahub/api2/endpoints/share_links.py
@@ -29,7 +29,7 @@ from seahub.api2.throttling import UserRateThrottle
from seahub.api2.permissions import CanGenerateShareLink, IsProVersion
from seahub.constants import PERMISSION_READ_WRITE, PERMISSION_READ, \
PERMISSION_PREVIEW_EDIT, PERMISSION_PREVIEW
-from seahub.share.models import FileShare, check_share_link_access
+from seahub.share.models import FileShare, UploadLinkShare, check_share_link_access
from seahub.utils import gen_shared_link, is_org_context, normalize_file_path, \
normalize_dir_path, is_pro_version, get_file_type_and_ext, \
check_filename_with_rename, gen_file_upload_url
@@ -47,6 +47,7 @@ from seahub.settings import SHARE_LINK_EXPIRE_DAYS_MAX, \
from seahub.wiki.models import Wiki
from seahub.views.file import can_edit_file
from seahub.views import check_folder_permission
+from seahub.signals import upload_file_successful
logger = logging.getLogger(__name__)
@@ -774,7 +775,7 @@ class ShareLinkUpload(APIView):
error_msg = 'Share link %s not found.' % token
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
- if share_link.s_type != 'd':
+ if not share_link.is_dir_share_link():
error_msg = 'Share link %s is not a folder share link.' % token
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
@@ -803,11 +804,15 @@ class ShareLinkUpload(APIView):
if not share_link.get_permissions()['can_upload']:
error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# generate token
obj_id = json.dumps({'parent_dir': path})
token = seafile_api.get_fileserver_access_token(repo_id,
- obj_id, 'upload-link', share_link.username, use_onetime=False)
+ obj_id,
+ 'upload-link',
+ share_link.username,
+ use_onetime=False)
if not token:
error_msg = 'Internal Server Error'
@@ -818,6 +823,137 @@ class ShareLinkUpload(APIView):
return Response(result)
+class ShareLinkUploadDone(APIView):
+
+ throttle_classes = (UserRateThrottle, )
+
+ def post(self, request, token):
+
+ """ Only used for saving notification after user upload file via folder share link and upload link.
+
+ Permission checking:
+ 1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated.
+ 2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited.
+ 3, If share link is encrypted, share link password must have been checked.
+ 4, Share link must be a folder share link and has can_upload permission.
+ """
+
+ # resource check
+
+ share_link = None
+ upload_link = None
+
+ try:
+ share_link = FileShare.objects.get(token=token)
+ except FileShare.DoesNotExist:
+ upload_link = UploadLinkShare.objects.get(token=token)
+ except UploadLinkShare.DoesNotExist:
+ error_msg = 'token %s not found.' % token
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ if share_link:
+
+ # check if login required
+ if SHARE_LINK_LOGIN_REQUIRED and \
+ not request.user.is_authenticated():
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ # check share link audit
+ if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \
+ not request.user.is_authenticated() and \
+ not request.session.get('anonymous_email'):
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ # check share link validation
+ if share_link.is_encrypted() and not check_share_link_access(request, token):
+ error_msg = 'Share link is encrypted.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if not share_link.get_permissions()['can_upload']:
+ error_msg = 'Share link has no can_upload permission'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if share_link.is_expired():
+ error_msg = 'Share link is expired'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if not share_link.is_dir_share_link():
+ error_msg = 'Share link %s is not a folder share link.' % token
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ # recourse check
+ repo_id = share_link.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)
+
+ parent_dir = share_link.path
+ if seafile_api.check_permission_by_path(repo_id, parent_dir, share_link.username) != 'rw':
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ file_path = request.data.get('file_path')
+ if not file_path:
+ error_msg = 'file_path invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ file_id = seafile_api.get_file_id_by_path(repo_id, file_path)
+ if not file_id:
+ error_msg = 'File %s not found.' % file_path
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # send singal
+ upload_file_successful.send(sender=None,
+ repo_id=repo_id,
+ file_path=file_path,
+ owner=share_link.username)
+
+ return Response({'success': True})
+
+ if upload_link:
+
+ if upload_link.is_encrypted() and not check_share_link_access(request,
+ token,
+ is_upload_link=True):
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ if upload_link.is_expired():
+ error_msg = 'Upload link is expired'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ repo_id = upload_link.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)
+
+ parent_dir = upload_link.path
+ if seafile_api.check_permission_by_path(repo_id, parent_dir, upload_link.username) != 'rw':
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ file_path = request.data.get('file_path')
+ if not file_path:
+ error_msg = 'file_path invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ file_id = seafile_api.get_file_id_by_path(repo_id, file_path)
+ if not file_id:
+ error_msg = 'File %s not found.' % file_path
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ upload_file_successful.send(sender=None,
+ repo_id=repo_id,
+ file_path=file_path,
+ owner=upload_link.username)
+
+ return Response({'success': True})
+
+
class ShareLinkSaveFileToRepo(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
diff --git a/seahub/urls.py b/seahub/urls.py
index 19425bcfe8..8ab11913a7 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -40,7 +40,8 @@ from seahub.api2.endpoints.group_members import GroupMembers, GroupMember, \
GroupMembersBulk, GroupMembersImport, GroupMembersImportExample
from seahub.api2.endpoints.search_group import SearchGroup
from seahub.api2.endpoints.share_links import ShareLinks, ShareLink, \
- ShareLinkOnlineOfficeLock, ShareLinkDirents, ShareLinkSaveFileToRepo, ShareLinkUpload
+ ShareLinkOnlineOfficeLock, ShareLinkDirents, ShareLinkSaveFileToRepo, \
+ ShareLinkUpload, ShareLinkUploadDone
from seahub.api2.endpoints.shared_folders import SharedFolders
from seahub.api2.endpoints.shared_repos import SharedRepos, SharedRepo
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink, \
@@ -336,6 +337,7 @@ urlpatterns = [
url(r'^api/v2.1/share-links/(?P[a-f0-9]+)/online-office-lock/$',
ShareLinkOnlineOfficeLock.as_view(), name='api-v2.1-share-link-online-office-lock'),
url(r'^api/v2.1/share-links/(?P[a-f0-9]+)/upload/$', ShareLinkUpload.as_view(), name='api-v2.1-share-link-upload'),
+ url(r'^api/v2.1/share-links/(?P[a-f0-9]+)/upload/done/$', ShareLinkUploadDone.as_view(), name='api-v2.1-share-link-upload-done'),
## user::shared-upload-links
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),