diff --git a/seahub/share/decorators.py b/seahub/share/decorators.py
index c373aae73f..ef4cac37f5 100644
--- a/seahub/share/decorators.py
+++ b/seahub/share/decorators.py
@@ -11,9 +11,10 @@ def share_link_audit(func):
def _decorated(request, token, *args, **kwargs):
assert token is not None # Checked by URLconf
- fileshare = FileShare.objects.get_valid_file_link_by_token(token)
- if fileshare is None:
- fileshare = UploadLinkShare.objects.get_valid_upload_link_by_token(token)
+ fileshare = FileShare.objects.get_valid_file_link_by_token(token) or \
+ FileShare.objects.get_valid_dir_link_by_token(token) or \
+ UploadLinkShare.objects.get_valid_upload_link_by_token(token)
+
if fileshare is None:
raise Http404
diff --git a/seahub/templates/view_shared_dir.html b/seahub/templates/view_shared_dir.html
index 471025f9bd..46e90d5f0a 100644
--- a/seahub/templates/view_shared_dir.html
+++ b/seahub/templates/view_shared_dir.html
@@ -87,7 +87,7 @@
{% if dirent.is_img %}
- {{ dirent.obj_name }}
+ {{ dirent.obj_name }}
{% else %}
{{ dirent.obj_name }}
{% endif %}
@@ -125,7 +125,7 @@
{% for dirent in file_list %}
{% if dirent.is_img %}
-
+
{% if dirent.encoded_thumbnail_src %}
{% else %}
@@ -139,7 +139,7 @@
{% endif %}
{% if dirent.is_img %}
- {{ dirent.obj_name }}
+ {{ dirent.obj_name }}
{% else %}
{{ dirent.obj_name }}
{% endif %}
diff --git a/seahub/views/file.py b/seahub/views/file.py
index 6a17595618..8981bf7d9a 100644
--- a/seahub/views/file.py
+++ b/seahub/views/file.py
@@ -896,14 +896,9 @@ def view_raw_shared_file(request, token, obj_id, file_name):
outer_url = gen_file_get_url(token, filename)
return HttpResponseRedirect(outer_url)
-def view_file_via_shared_dir(request, token):
- assert token is not None # Checked by URLconf
-
- fileshare = FileShare.objects.get_valid_file_link_by_token(token)
- if fileshare is None:
- raise Http404
-
-
+@share_link_audit
+def view_file_via_shared_dir(request, fileshare):
+ token = fileshare.token
req_path = request.GET.get('p', '').rstrip('/')
if not req_path:
return HttpResponseRedirect(reverse('view_shared_dir', args=[token]))
@@ -941,9 +936,19 @@ def view_file_via_shared_dir(request, token):
obj_id = seafile_api.get_file_id_by_path(repo_id, real_path)
if not obj_id:
return render_error(request, _(u'File does not exist'))
- file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)
filename = os.path.basename(req_path)
+ if request.GET.get('raw', '0') == '1':
+ username = request.user.username
+ token = seafile_api.get_fileserver_access_token(repo_id,
+ obj_id, 'view', username, use_onetime=True)
+
+ raw_url = gen_file_get_url(token, filename)
+ # send stats message
+ send_file_access_msg(request, repo, real_path, 'share-link')
+ return HttpResponseRedirect(raw_url)
+
+ file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)
filetype, fileext = get_file_type_and_ext(filename)
access_token = seafile_api.get_fileserver_access_token(repo.id, obj_id,
'view', '', use_onetime=False)
diff --git a/tests/seahub/share/test_decorators.py b/tests/seahub/share/test_decorators.py
new file mode 100644
index 0000000000..31ff58fee6
--- /dev/null
+++ b/tests/seahub/share/test_decorators.py
@@ -0,0 +1,143 @@
+from mock import patch
+
+from django.core.cache import cache
+from django.contrib.auth.models import AnonymousUser
+from django.http import HttpResponse, Http404
+from django.test import override_settings
+from django.test.client import RequestFactory
+
+from seahub.test_utils import BaseTestCase
+from seahub.share.decorators import share_link_audit
+from seahub.share.models import FileShare
+from seahub.utils import gen_token, normalize_cache_key
+
+class ShareLinkAuditTest(BaseTestCase):
+ def setUp(self):
+ share_file_info = {
+ 'username': self.user.username,
+ 'repo_id': self.repo.id,
+ 'path': self.file,
+ 'password': None,
+ 'expire_date': None,
+ }
+ self.fs = FileShare.objects.create_file_link(**share_file_info)
+
+ # Every test needs access to the request factory.
+ self.factory = RequestFactory()
+
+ @property
+ def _request(self, session={}):
+ request = self.factory.get('/rand')
+ request.user = self.user
+ request.session = session
+ return request
+
+ def _anon_request(self, session={}):
+ request = self.factory.get('/rand')
+ request.user = AnonymousUser()
+ request.session = session
+ request.cloud_mode = False
+ return request
+
+ def _anon_post_request(self, data={}, session={}):
+ request = self.factory.post('/rand', data)
+ request.user = AnonymousUser()
+ request.session = session
+ request.cloud_mode = False
+ return request
+
+ def _fake_view_shared_file(self, request, token):
+ @share_link_audit
+ def fake_view_shared_file(request, fileshare):
+ return HttpResponse()
+ return fake_view_shared_file(request, token)
+
+ def test_bad_share_token(self):
+ @share_link_audit
+ def a_view(request, fileshare):
+ return HttpResponse()
+
+ request = self.factory.get('/rand')
+ request.user = self.user
+
+ self.assertRaises(Http404, a_view, request, 'xxx')
+
+ def test_non_pro_version(self):
+ """
+ Check that share_link_audit works as nomal view_shared_file on
+ non-pro version.
+ """
+ resp = self._fake_view_shared_file(self._request, self.fs.token)
+ self.assertEqual(resp.status_code, 200)
+
+ def test_shared_link_audit_not_enabled(self):
+ resp = self._fake_view_shared_file(self._request, self.fs.token)
+ self.assertEqual(resp.status_code, 200)
+
+ @override_settings(ENABLE_SHARE_LINK_AUDIT=True)
+ @patch('seahub.share.decorators.is_pro_version')
+ def test_audit_authenticated_user(self, mock_is_pro_version):
+ mock_is_pro_version.return_value = True
+
+ resp = self._fake_view_shared_file(self._request, self.fs.token)
+ self.assertEqual(resp.status_code, 200)
+
+ @override_settings(ENABLE_SHARE_LINK_AUDIT=True)
+ @patch('seahub.share.decorators.is_pro_version')
+ def test_audit_anonymous_user_with_mail_in_session(self, mock_is_pro_version):
+ mock_is_pro_version.return_value = True
+
+ anon_req = self._anon_request(session={'anonymous_email': 'a@a.com'})
+ resp = self._fake_view_shared_file(anon_req, self.fs.token)
+ self.assertEqual(resp.status_code, 200)
+
+ @override_settings(ENABLE_SHARE_LINK_AUDIT=True)
+ @patch('seahub.share.decorators.is_pro_version')
+ def test_audit_anonymous_user_without_mail_in_session(self, mock_is_pro_version):
+ """
+ Check that share_link_audit works on pro version and setting enabled,
+ which show a page that let user input email and verification code.
+ """
+ mock_is_pro_version.return_value = True
+
+ anon_req = self._anon_request()
+ resp = self._fake_view_shared_file(anon_req, self.fs.token)
+ self.assertEqual(resp.status_code, 200)
+ self.assertIn('Please provide your email address to continue. ', resp.content)
+
+ @override_settings(ENABLE_SHARE_LINK_AUDIT=True)
+ @patch('seahub.share.decorators.is_pro_version')
+ def test_anonymous_user_post_wrong_token(self, mock_is_pro_version):
+ """
+ Check that anonnymous user input email and wrong verification code.
+ """
+ mock_is_pro_version.return_value = True
+
+ anon_req = self._anon_post_request(data={'code': 'xx'}, session={})
+ self.assertEqual(anon_req.session.get('anonymous_email'), None)
+ resp = self._fake_view_shared_file(anon_req, self.fs.token)
+
+ self.assertEqual(resp.status_code, 200)
+ self.assertIn('Invalid token, please try again.', resp.content)
+
+ @override_settings(ENABLE_SHARE_LINK_AUDIT=True)
+ @patch('seahub.share.decorators.is_pro_version')
+ def test_anonymous_user_post_correct_token(self, mock_is_pro_version):
+ """
+ Check that anonnymous user input email and correct verification code.
+ """
+ mock_is_pro_version.return_value = True
+
+ code = gen_token(max_length=6)
+ email = 'a@a.com'
+ cache_key = normalize_cache_key(email, 'share_link_audit_')
+ cache.set(cache_key, code, timeout=60)
+ assert cache.get(cache_key) == code
+
+ anon_req = self._anon_post_request(data={'code': code, 'email': email})
+ self.assertEqual(anon_req.session.get('anonymous_email'), None)
+ resp = self._fake_view_shared_file(anon_req, self.fs.token)
+
+ self.assertEqual(resp.status_code, 200)
+ self.assertEqual(anon_req.session.get('anonymous_email'), email) # email is set in session
+ assert cache.get(cache_key) is None # token is delete after used
diff --git a/tests/seahub/views/repo/test_shared_dir.py b/tests/seahub/views/repo/test_shared_dir.py
index 48a5428b79..e278c3d33e 100644
--- a/tests/seahub/views/repo/test_shared_dir.py
+++ b/tests/seahub/views/repo/test_shared_dir.py
@@ -38,6 +38,13 @@ class SharedDirTest(TestCase, Fixtures):
self.assertEqual(302, resp.status_code)
assert '8082/files/' in resp.get('location')
+ def test_view_raw_file_via_shared_dir(self):
+ resp = self.client.get(
+ reverse('view_file_via_shared_dir', args=[self.fs.token]) + '?p=' + self.file + '&raw=1'
+ )
+
+ assert '8082' in resp['location']
+
class EncryptSharedDirTest(TestCase, Fixtures):
def setUp(self):
share_file_info = {
@@ -124,6 +131,24 @@ class EncryptSharedDirTest(TestCase, Fixtures):
self.assertTemplateUsed(resp, 'shared_file_view.html')
self.assertContains(resp, '%s' % self.filename)
+ def test_view_raw_file_via_shared_dir(self):
+ resp = self.client.post(
+ reverse('view_file_via_shared_dir', args=[self.fs.token]) + '?p=' + self.sub_file, {
+ 'password': '12345678'
+ }
+ )
+
+ self.assertEqual(200, resp.status_code)
+ self.assertTemplateNotUsed(resp, 'share_access_validation.html')
+ self.assertTemplateUsed(resp, 'shared_file_view.html')
+ self.assertContains(resp, '%s' % self.filename)
+
+ resp = self.client.get(
+ reverse('view_file_via_shared_dir', args=[self.fs.token]) + '?p=' + self.sub_file + '&raw=1'
+ )
+
+ assert '8082' in resp['location']
+
def test_view_file_via_shared_dir_without_password(self):
resp = self.client.get(
reverse('view_file_via_shared_dir', args=[self.fs.token]) + '?p=' + self.sub_file
|