From cc225f3bb090390c2918bd75b8c76aa10695c31f Mon Sep 17 00:00:00 2001 From: Shuai Lin Date: Wed, 8 Jul 2015 10:33:07 +0800 Subject: [PATCH 01/13] fixed office preview permission check --- seahub/templates/snippets/office_convert_js.html | 3 ++- seahub/views/file.py | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/seahub/templates/snippets/office_convert_js.html b/seahub/templates/snippets/office_convert_js.html index e9c5a44abe..c06a528a84 100644 --- a/seahub/templates/snippets/office_convert_js.html +++ b/seahub/templates/snippets/office_convert_js.html @@ -20,7 +20,8 @@ var OfficePreviewer = function(file_id, preview_token) { $.param({file_id: this.file_id, page: page}); } this.page_content_url = function(page) { - return "{% url 'office_convert_get_page' obj_id %}/" + page + '.page'; + return "{% url 'office_convert_get_page' obj_id %}/" + + page + '.page?office_preview_token=' + this.preview_token; } var url = window.location.href; diff --git a/seahub/views/file.py b/seahub/views/file.py index 37f76f3eb9..a83e250745 100644 --- a/seahub/views/file.py +++ b/seahub/views/file.py @@ -1382,11 +1382,11 @@ def office_convert_get_page(request, path, internal=False): return HttpResponseForbidden() file_id = m.group(1) - # if path.endswith('file.css'): - # pass - # else: - # if request.office_preview_token != do_md5(file_id + settings.SECRET_KEY): - # return HttpResponseForbidden() + if path.endswith('file.css'): + pass + else: + if request.office_preview_token != do_md5(file_id + settings.SECRET_KEY): + return HttpResponseForbidden() resp = get_office_converted_page(request, path, file_id, internal=internal) resp['Content-Type'] = 'text/html' From 2cd615d561ce33c629660060c81cbdf27c3e54c9 Mon Sep 17 00:00:00 2001 From: zhengxie Date: Wed, 8 Jul 2015 14:37:25 +0800 Subject: [PATCH 02/13] Fix user last login duplicate error --- seahub/auth/tokens.py | 8 ++++---- seahub/base/models.py | 23 ++++++++++++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/seahub/auth/tokens.py b/seahub/auth/tokens.py index 1599f533c8..91bb013a89 100644 --- a/seahub/auth/tokens.py +++ b/seahub/auth/tokens.py @@ -57,12 +57,12 @@ class PasswordResetTokenGenerator(object): key_salt = "django.contrib.auth.tokens.PasswordResetTokenGenerator" # Ensure results are consistent across DB backends - try: - user_last_login = UserLastLogin.objects.get(username=user.email) - login_dt = user_last_login.last_login - except UserLastLogin.DoesNotExist: + user_last_login = UserLastLogin.objects.get_by_username(user.username) + if user_last_login is None: from seahub.utils.timeutils import dt login_dt = dt(user.ctime) + else: + login_dt = user_last_login.last_login login_timestamp = login_dt.replace(microsecond=0, tzinfo=None) value = (six.text_type(user.id) + user.enc_password + diff --git a/seahub/base/models.py b/seahub/base/models.py index 05103e7f5c..e16347251d 100644 --- a/seahub/base/models.py +++ b/seahub/base/models.py @@ -152,18 +152,35 @@ class GroupEnabledModule(models.Model): module_name = models.CharField(max_length=20) ########## misc +class UserLastLoginManager(models.Manager): + def get_by_username(self, username): + """Return last login record for a user, delete duplicates if there are + duplicated records. + """ + try: + return self.get(username=username) + except UserLastLogin.DoesNotExist: + return None + except UserLastLogin.MultipleObjectsReturned: + dups = self.filter(username=username) + ret = dups[0] + for dup in dups[1:]: + dup.delete() + logger.warn('Delete duplicate user last login record: %s' % username) + return ret + class UserLastLogin(models.Model): username = models.CharField(max_length=255, db_index=True) last_login = models.DateTimeField(default=timezone.now) + objects = UserLastLoginManager() def update_last_login(sender, user, **kwargs): """ A signal receiver which updates the last_login date for the user logging in. """ - try: - user_last_login = UserLastLogin.objects.get(username=user.username) - except UserLastLogin.DoesNotExist: + user_last_login = UserLastLogin.objects.get_by_username(user.username) + if user_last_login is None: user_last_login = UserLastLogin(username=user.username) user_last_login.last_login = timezone.now() user_last_login.save() From a47a15e5e3e1be7049a783d7f2d08a387b25bf5c Mon Sep 17 00:00:00 2001 From: zhengxie Date: Thu, 9 Jul 2015 15:49:04 +0800 Subject: [PATCH 03/13] Fix license parsing bug in fastcgi mode --- seahub/views/sysadmin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index 39ed0496d9..cd60ae4c15 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -88,7 +88,8 @@ def sys_info(request): is_pro = is_pro_version() if is_pro: - license_dict = parse_license('../seafile-license.txt') + license_file = os.path.join(settings.PROJECT_ROOT, '../../seafile-license.txt') + license_dict = parse_license(license_file) else: license_dict = {} return render_to_response('sysadmin/sys_info.html', { From 0f65ddfae51511590a976f54dd22aa6b194d6eab Mon Sep 17 00:00:00 2001 From: zhengxie Date: Fri, 10 Jul 2015 16:32:48 +0800 Subject: [PATCH 04/13] Fix forbiden issue in dir upload link --- seahub/views/ajax.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/seahub/views/ajax.py b/seahub/views/ajax.py index e757a85d86..12637748a0 100644 --- a/seahub/views/ajax.py +++ b/seahub/views/ajax.py @@ -1854,8 +1854,7 @@ def get_file_upload_url_ul(request, token): status=403, content_type=content_type) acc_token = seafile_api.get_fileserver_access_token(repo_id, 'dummy', - 'upload', - request.user.username, + 'upload', '', use_onetime=False) url = gen_file_upload_url(acc_token, 'upload-aj') return HttpResponse(json.dumps({"url": url}), content_type=content_type) From 61dff076d426ada24689356b6f1a08076bb78bcf Mon Sep 17 00:00:00 2001 From: zhengxie Date: Mon, 13 Jul 2015 11:56:09 +0800 Subject: [PATCH 05/13] Fix dir/file api path not exists error --- seahub/api2/views.py | 5 ++++- seahub/base/models.py | 5 ++++- seahub/group/views.py | 5 ++++- seahub/utils/repo.py | 3 ++- seahub/views/__init__.py | 4 ++++ seahub/views/file.py | 5 ++++- seahub/views/repo.py | 3 +++ seahub/views/wiki.py | 6 +++++- seahub/wiki/utils.py | 2 ++ 9 files changed, 32 insertions(+), 6 deletions(-) diff --git a/seahub/api2/views.py b/seahub/api2/views.py index ae64fdcc28..6475e66738 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -1852,7 +1852,10 @@ class FileDetailView(APIView): # get real path for sub repo real_path = repo.origin_path + path if repo.origin_path else path dirent = seafile_api.get_dirent_by_path(repo.store_id, real_path) - latest_contributor, last_modified = dirent.modifier, dirent.mtime + if dirent: + latest_contributor, last_modified = dirent.modifier, dirent.mtime + else: + latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 diff --git a/seahub/base/models.py b/seahub/base/models.py index e16347251d..cdc4ada20f 100644 --- a/seahub/base/models.py +++ b/seahub/base/models.py @@ -120,7 +120,10 @@ class UserStarredFilesManager(models.Manager): real_path = sfile.repo.origin_path + sfile.path if sfile.repo.origin_path else sfile.path dirent = seafile_api.get_dirent_by_path(sfile.repo.store_id, real_path) - sfile.last_modified = dirent.mtime + if dirent: + sfile.last_modified = dirent.mtime + else: + sfile.last_modified = 0 except SearpcError as e: logger.error(e) sfile.last_modified = 0 diff --git a/seahub/group/views.py b/seahub/group/views.py index 8073836400..6c710d1308 100644 --- a/seahub/group/views.py +++ b/seahub/group/views.py @@ -1396,7 +1396,10 @@ def group_wiki(request, group, page_name="home"): path = '/' + dirent.obj_name try: dirent = seafile_api.get_dirent_by_path(repo.id, path) - latest_contributor, last_modified = dirent.modifier, dirent.mtime + if dirent: + latest_contributor, last_modified = dirent.modifier, dirent.mtime + else: + latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 diff --git a/seahub/utils/repo.py b/seahub/utils/repo.py index 532bdb85b6..e8e1e28e7d 100644 --- a/seahub/utils/repo.py +++ b/seahub/utils/repo.py @@ -15,7 +15,8 @@ def list_dir_by_path(cmmt, path): if cmmt.root_id == EMPTY_SHA1: return [] else: - return seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id, path) + dirs = seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id, path) + return dirs if dirs else [] def get_sub_repo_abbrev_origin_path(repo_name, origin_path): """Return abbrev path for sub repo based on `repo_name` and `origin_path`. diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py index b3e1f8814b..413b758712 100644 --- a/seahub/views/__init__.py +++ b/seahub/views/__init__.py @@ -202,6 +202,8 @@ def get_repo_dirents_with_perm(request, repo, commit, path, offset=-1, limit=-1) else: try: dir_id = seafile_api.get_dir_id_by_path(repo.id, path) + if not dir_id: + return ([], [], False) dirs = seafserv_threaded_rpc.list_dir_with_perm(repo.id, path, dir_id, username, offset, limit) @@ -285,6 +287,8 @@ def get_repo_dirents(request, repo, commit, path, offset=-1, limit=-1): dirs = seafile_api.list_dir_by_commit_and_path(commit.repo_id, commit.id, path, offset, limit) + if not dirs: + return ([], [], False) except SearpcError as e: logger.error(e) return ([], [], False) diff --git a/seahub/views/file.py b/seahub/views/file.py index a83e250745..74107b8390 100644 --- a/seahub/views/file.py +++ b/seahub/views/file.py @@ -442,7 +442,10 @@ def _file_view(request, repo_id, path): # get real path for sub repo real_path = repo.origin_path + path if repo.origin_path else path dirent = seafile_api.get_dirent_by_path(repo.store_id, real_path) - latest_contributor, last_modified = dirent.modifier, dirent.mtime + if dirent: + latest_contributor, last_modified = dirent.modifier, dirent.mtime + else: + latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 diff --git a/seahub/views/repo.py b/seahub/views/repo.py index fc3ab4a1e6..2dd4531c42 100644 --- a/seahub/views/repo.py +++ b/seahub/views/repo.py @@ -374,6 +374,9 @@ def _download_dir_from_share_link(request, fileshare, repo, real_path): dirname = os.path.basename(real_path.rstrip('/')) dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path) + if not dir_id: + return render_error( + request, _(u'Unable to download: folder not found.')) try: total_size = seaserv.seafserv_threaded_rpc.get_dir_size( diff --git a/seahub/views/wiki.py b/seahub/views/wiki.py index 8771905ed0..0ab21cf42f 100644 --- a/seahub/views/wiki.py +++ b/seahub/views/wiki.py @@ -66,8 +66,12 @@ def personal_wiki(request, page_name="home"): path = '/' + dirent.obj_name try: dirent = seafile_api.get_dirent_by_path(repo.id, path) - latest_contributor, last_modified = dirent.modifier, dirent.mtime + if dirent: + latest_contributor, last_modified = dirent.modifier, dirent.mtime + else: + latest_contributor, last_modified = None, 0 except SearpcError as e: + logger.error(e) latest_contributor, last_modified = None, 0 wiki_index_exists = True diff --git a/seahub/wiki/utils.py b/seahub/wiki/utils.py index 456cc5f857..6a4b7a3de3 100644 --- a/seahub/wiki/utils.py +++ b/seahub/wiki/utils.py @@ -98,6 +98,8 @@ def get_wiki_pages(repo): return pages in hashtable {normalized_name: page_name} """ dir_id = seaserv.seafserv_threaded_rpc.get_dir_id_by_path(repo.id, '/') + if not dir_id: + return {} dirs = seafile_api.list_dir_by_dir_id(repo.id, dir_id) pages = {} for e in dirs: From 6ff2efb5970e5b695f4857c1da7f53df51650e75 Mon Sep 17 00:00:00 2001 From: llj Date: Fri, 26 Jun 2015 15:45:15 +0800 Subject: [PATCH 06/13] [dir private share] split into user/group share --- media/css/seahub.css | 4 + seahub/share/urls.py | 1 + seahub/share/views.py | 2 +- seahub/templates/js/templates.html | 75 +++++--- seahub/urls.py | 3 + seahub/views/ajax.py | 86 ++++++++- static/scripts/app/views/folder-perm-item.js | 18 +- static/scripts/app/views/folder-perm.js | 8 +- static/scripts/app/views/folder-share-item.js | 96 ++++++++++ static/scripts/app/views/share.js | 173 ++++++++++++++---- static/scripts/common.js | 3 + 11 files changed, 396 insertions(+), 73 deletions(-) create mode 100644 static/scripts/app/views/folder-share-item.js diff --git a/media/css/seahub.css b/media/css/seahub.css index 0fb590a228..28a5128016 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -3545,16 +3545,20 @@ textarea:-moz-placeholder {/* for FF */ } /* user & group folder perm */ +#share-popup .tabs-panel, #folder-perm-tabs .tabs-panel { width:550px; } +#share-popup .share-permission-select, #folder-perm-tabs .perm-select { height:30px; } +#share-popup .submit, #folder-perm-tabs .submit { margin-top:2px; height:30px; } +#share-popup table, #folder-perm-tabs table { margin-top:0; } diff --git a/seahub/share/urls.py b/seahub/share/urls.py index 9f7a1172b3..17eb5f4a0a 100644 --- a/seahub/share/urls.py +++ b/seahub/share/urls.py @@ -37,5 +37,6 @@ urlpatterns = patterns('', url(r'^ajax/get-download-link/$', ajax_get_download_link, name='ajax_get_download_link'), url(r'^ajax/get-upload-link/$', ajax_get_upload_link, name='ajax_get_upload_link'), url(r'^ajax/private-share-file/$', ajax_private_share_file, name='ajax_private_share_file'), + url(r'^ajax/private-share-dir/$', ajax_private_share_dir, name='ajax_private_share_dir'), ) diff --git a/seahub/share/views.py b/seahub/share/views.py index 30cd5d54ff..0e36f84870 100644 --- a/seahub/share/views.py +++ b/seahub/share/views.py @@ -359,7 +359,7 @@ def ajax_repo_remove_share(request): @login_required def repo_remove_share(request): """ - If repo is shared from one person to another person, only these two peson + If repo is shared from one person to another person, only these two person can remove share. If repo is shared from one person to a group, then only the one share the repo and group staff can remove share. diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html index c7b972e352..af1e6bfb80 100644 --- a/seahub/templates/js/templates.html +++ b/seahub/templates/js/templates.html @@ -328,8 +328,9 @@ <% if (user_perm == 'rw' && !repo_encrypted) { %>
  • {% trans "Upload Link" %}
  • <% } %> - <% if (!is_virtual && is_repo_owner) { %> -
  • {% trans "Private Share" %}
  • + <% if (!is_virtual && is_repo_owner) { %> {# dir private share #} +
  • {% trans "Share to user" %}
  • +
  • {% trans "Share to group" %}
  • <% } %> <% } %> @@ -423,28 +424,56 @@ <% if (!is_virtual && is_repo_owner) { %> <% if (!repo_encrypted) { %> -
    +
    <% } else { %> -
    {# enc lib only has 'dir-private-share' #} +
    <% } %> -
    -
    -
    - -
    -
    - -
    - -

    - -
    + + + + + + + + + + + +
    {% trans "User" %}{% trans "Permission" %}
    + + + +
    +

    - <% } %> - <% } %> + +
    + + + + + + + + + + + +
    {% trans "Group" %}{% trans "Permission" %}
    + + + +
    +

    +
    + <% } %> {# if (!is_virtual && is_repo_owner) #} + <% } %> {# if is_dir #} <% if (!is_dir && is_repo_owner) { %>
    @@ -608,7 +637,7 @@