diff --git a/media/css/mobile.css b/media/css/mobile.css index 99369d3b35..967eb4d780 100644 --- a/media/css/mobile.css +++ b/media/css/mobile.css @@ -1195,6 +1195,7 @@ textarea:-moz-placeholder {/* for FF */ } /*repo-share-form*/ #link-send-input, +#upload-link-send-input, #email_or_group, #share-link, #added-member-name, @@ -1426,10 +1427,13 @@ textarea:-moz-placeholder {/* for FF */ text-align:right; } #shared-link, -#shared-link-text { +#shared-upload-link, +#shared-link-text, +#shared-upload-link-text { border:0; } -#shared-link-text { +#shared-link-text, +#shared-upload-link-text { vertical-align:middle; /*for ie 7*/ } .file-op { diff --git a/media/css/seahub.css b/media/css/seahub.css index 9714669e8d..0e9fd4e0e3 100644 --- a/media/css/seahub.css +++ b/media/css/seahub.css @@ -1542,6 +1542,7 @@ textarea:-moz-placeholder {/* for FF */ } /*repo-share-form*/ #link-send-input, +#upload-link-send-input, #email_or_group, #share-link, #added-member-name { @@ -1623,7 +1624,7 @@ textarea:-moz-placeholder {/* for FF */ left:365px; top:50px; z-index:10; - padding:15px;; + padding:15px; min-height:130px; border:1px solid #ddd; background:#fff; @@ -1944,10 +1945,13 @@ textarea:-moz-placeholder {/* for FF */ text-align:right; } #shared-link, -#shared-link-text { +#shared-upload-link, +#shared-link-text, +#shared-upload-link-text { border:0; } -#shared-link-text { +#shared-link-text, +#shared-upload-link-text { background:transparent; height:auto; } diff --git a/seahub/share/forms.py b/seahub/share/forms.py index c7a093748a..fc4aeddf27 100644 --- a/seahub/share/forms.py +++ b/seahub/share/forms.py @@ -21,3 +21,12 @@ class FileLinkShareForm(forms.Form): }) file_shared_link = forms.CharField() +class UploadLinkShareForm(forms.Form): + """ + Form for sharing upload link to emails. + """ + email = forms.CharField(max_length=512, error_messages={ + 'required': _("Email is required"), + 'max_length': _("Email is not longer than 512 characters"), + }) + shared_upload_link = forms.CharField() diff --git a/seahub/share/models.py b/seahub/share/models.py index 1d26f49c79..9c59a461ae 100644 --- a/seahub/share/models.py +++ b/seahub/share/models.py @@ -25,6 +25,16 @@ class FileShare(models.Model): view_cnt = models.IntegerField(default=0) s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d` +class UploadLinkShare(models.Model): + """ + Model used for shared upload link. + """ + username = LowerCaseCharField(max_length=255, db_index=True) + repo_id = models.CharField(max_length=36, db_index=True) + path = models.TextField() + token = models.CharField(max_length=10, unique=True) + ctime = models.DateTimeField(default=datetime.datetime.now) + view_cnt = models.IntegerField(default=0) class PrivateFileDirShareManager(models.Manager): def add_private_file_share(self, from_user, to_user, repo_id, path, perm): diff --git a/seahub/share/templates/repo/priv_shared_files.html b/seahub/share/templates/repo/priv_shared_files.html index e8bec38a02..8f86f217c5 100644 --- a/seahub/share/templates/repo/priv_shared_files.html +++ b/seahub/share/templates/repo/priv_shared_files.html @@ -6,13 +6,7 @@ {% block nav_share_class %}class="cur"{% endblock %} {% block title_panel %} -
- -
+{% include "repo/tabnav.html" with cur="private" %} {% endblock %} {% block main_panel %} diff --git a/seahub/share/templates/repo/share_out_repos.html b/seahub/share/templates/repo/share_out_repos.html index 6b552aec95..5441584556 100644 --- a/seahub/share/templates/repo/share_out_repos.html +++ b/seahub/share/templates/repo/share_out_repos.html @@ -6,13 +6,7 @@ {% block nav_share_class %}class="cur"{% endblock %} {% block title_panel %} -
- -
+{% include "repo/tabnav.html" with cur="library" %} {% endblock %} {% block main_panel %} diff --git a/seahub/share/templates/repo/shared_links.html b/seahub/share/templates/repo/shared_links.html index fd2eb8b845..87488e11ab 100644 --- a/seahub/share/templates/repo/shared_links.html +++ b/seahub/share/templates/repo/shared_links.html @@ -6,13 +6,7 @@ {% block nav_share_class %}class="cur"{% endblock %} {% block title_panel %} -
- -
+{% include "repo/tabnav.html" with cur="links" %} {% endblock %} {% block main_panel %} diff --git a/seahub/share/templates/repo/shared_upload_links.html b/seahub/share/templates/repo/shared_upload_links.html new file mode 100644 index 0000000000..5c0df4d27f --- /dev/null +++ b/seahub/share/templates/repo/shared_upload_links.html @@ -0,0 +1,61 @@ +{% extends base_template %} +{% load seahub_tags i18n %} +{% load url from future %} + +{% block sub_title %}{% trans "Share" %} - {% endblock %} +{% block nav_share_class %}class="cur"{% endblock %} + +{% block title_panel %} +{% include "repo/tabnav.html" with cur="upload" %} +{% endblock %} + +{% block main_panel %} +{% if uploadlinks %} + + + + + + + + + {% for link in uploadlinks %} + + + + + + + + {% endfor %} + + +{% else %} +
+

{% trans "You don't have any shared upload link"%}

+

{% trans "You can share a folder with other users so that they can upload files to your folder." %}

+
+{% endif %} + +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/share/templates/repo/tabnav.html b/seahub/share/templates/repo/tabnav.html new file mode 100644 index 0000000000..e6bc7eedc3 --- /dev/null +++ b/seahub/share/templates/repo/tabnav.html @@ -0,0 +1,10 @@ +{% load i18n %} + +
+ +
diff --git a/seahub/share/urls.py b/seahub/share/urls.py index 21a0b21806..4534866339 100644 --- a/seahub/share/urls.py +++ b/seahub/share/urls.py @@ -5,6 +5,7 @@ from views import * urlpatterns = patterns('', url(r'^$', list_share_out_repos, name='share_admin'), url(r'^links/$', list_shared_links, name='list_shared_links'), + url(r'^upload_links/$', list_shared_upload_links, name='list_shared_upload_links'), url(r'^files/$', list_priv_shared_files, name='list_priv_shared_files'), url(r'^add/$', share_repo, name='share_repo'), @@ -15,6 +16,10 @@ urlpatterns = patterns('', url(r'^link/send/$', send_shared_link, name='send_shared_link'), url(r'^link/save/$', save_shared_link, name='save_shared_link'), + url(r'^upload_link/get/$', get_shared_upload_link, name='get_shared_upload_link'), + url(r'^upload_link/remove/$', remove_shared_upload_link, name='remove_shared_upload_link'), + url(r'^upload_link/send/$', send_shared_upload_link, name='send_shared_upload_link'), + url(r'^permission_admin/$', share_permission_admin, name='share_permission_admin'), diff --git a/seahub/share/views.py b/seahub/share/views.py index 7f190c95bf..d754d4a07a 100644 --- a/seahub/share/views.py +++ b/seahub/share/views.py @@ -23,8 +23,8 @@ from seaserv import seafserv_threaded_rpc, ccnet_rpc, \ del_org_group_repo, list_share_repos, get_group_repos_by_owner, \ list_inner_pub_repos_by_owner, remove_share -from forms import RepoShareForm, FileLinkShareForm -from models import AnonymousShare, FileShare, PrivateFileDirShare +from forms import RepoShareForm, FileLinkShareForm, UploadLinkShareForm +from models import AnonymousShare, FileShare, PrivateFileDirShare, UploadLinkShare from signals import share_repo_to_user_successful from settings import ANONYMOUS_SHARE_COOKIE_TIMEOUT from tokens import anon_share_token_generator @@ -35,8 +35,8 @@ from seahub.contacts.signals import mail_sended from seahub.signals import share_file_to_user_successful from seahub.views import validate_owner, is_registered_user from seahub.utils import render_permission_error, string2list, render_error, \ - gen_token, gen_shared_link, gen_dir_share_link, gen_file_share_link, \ - IS_EMAIL_CONFIGURED, check_filename_with_rename + gen_token, gen_shared_link, gen_shared_upload_link, gen_dir_share_link, \ + gen_file_share_link, IS_EMAIL_CONFIGURED, check_filename_with_rename try: from seahub.settings import CLOUD_MODE @@ -399,6 +399,32 @@ def list_shared_links(request): "fileshares": p_fileshares, }, context_instance=RequestContext(request)) +@login_required +def list_shared_upload_links(request): + """List upload links, and remove invalid links(dir is deleted or moved). + """ + username = request.user.username + + uploadlinks = UploadLinkShare.objects.filter(username=username) + p_uploadlinks = [] + for link in uploadlinks: + if is_personal_repo(link.repo_id): + r = seafile_api.get_repo(link.repo_id) + if not r: + link.delete() + continue + if seafile_api.get_dir_id_by_path(r.id, link.path) is None: + link.delete() + continue + link.filename = os.path.basename(link.path.rstrip('/')) + link.shared_link = gen_shared_upload_link(link.token) + link.repo = r + p_uploadlinks.append(link) + + return render_to_response('repo/shared_upload_links.html', { + "uploadlinks": p_uploadlinks, + }, context_instance=RequestContext(request)) + @login_required def list_priv_shared_files(request): """List private shared files. @@ -629,6 +655,39 @@ def remove_shared_link(request): result = {'error': _(u"The link doesn't exist")} return HttpResponse(json.dumps(result), status=400, content_type=content_type) +@login_required +def remove_shared_upload_link(request): + """ + Handle request to remove shared upload link. + """ + token = request.GET.get('t') + + if not request.is_ajax(): + UploadLinkShare.objects.filter(token=token).delete() + next = request.META.get('HTTP_REFERER', None) + if not next: + next = reverse('share_admin') + + messages.success(request, _(u'Removed successfully')) + + return HttpResponseRedirect(next) + + content_type = 'application/json; charset=utf-8' + result = {} + + if not token: + result = {'error': _(u"Argument missing")} + return HttpResponse(json.dumps(result), status=400, content_type=content_type) + + try: + upload_link = UploadLinkShare.objects.get(token=token) + upload_link.delete() + result = {'success': True} + return HttpResponse(json.dumps(result), content_type=content_type) + except: + result = {'error': _(u"The link doesn't exist")} + return HttpResponse(json.dumps(result), status=400, content_type=content_type) + @login_required def send_shared_link(request): """ @@ -845,3 +904,102 @@ def user_share_list(request, id_or_email): 'add_to_contacts': add_to_contacts, }, context_instance=RequestContext(request)) +@login_required +def get_shared_upload_link(request): + """ + Handle ajax request to generate dir upload link. + """ + if not request.is_ajax(): + raise Http404 + content_type = 'application/json; charset=utf-8' + + repo_id = request.GET.get('repo_id', '') + path = request.GET.get('p', '') + + if not (repo_id and path): + err = _('Invalid arguments') + data = json.dumps({'error': err}) + return HttpResponse(data, status=400, content_type=content_type) + + if path == '/': # can not share root dir + err = _('You cannot share the library in this way.') + data = json.dumps({'error': err}) + return HttpResponse(data, status=400, content_type=content_type) + else: + if path[-1] != '/': # append '/' at end of path + path += '/' + l = UploadLinkShare.objects.filter(repo_id=repo_id).filter( + username=request.user.username).filter(path=path) + if len(l) > 0: + upload_link = l[0] + token = upload_link.token + else: + token = gen_token(max_length=10) + + upload_link = UploadLinkShare() + upload_link.username = request.user.username + upload_link.repo_id = repo_id + upload_link.path = path + upload_link.token = token + + try: + upload_link.save() + except IntegrityError, e: + err = _('Failed to get the link, please retry later.') + data = json.dumps({'error': err}) + return HttpResponse(data, status=500, content_type=content_type) + + shared_upload_link = gen_shared_upload_link(token) + + data = json.dumps({'token': token, 'shared_upload_link': shared_upload_link}) + return HttpResponse(data, status=200, content_type=content_type) + +@login_required +def send_shared_upload_link(request): + """ + Handle ajax post request to send shared upload link. + """ + if not request.is_ajax() and not request.method == 'POST': + raise Http404 + + content_type = 'application/json; charset=utf-8' + + if not IS_EMAIL_CONFIGURED: + data = json.dumps({'error':_(u'Sending shared upload link failed. Email service is not properly configured, please contact administrator.')}) + return HttpResponse(data, status=500, content_type=content_type) + + from seahub.settings import SITE_NAME + + form = UploadLinkShareForm(request.POST) + if form.is_valid(): + email = form.cleaned_data['email'] + shared_upload_link = form.cleaned_data['shared_upload_link'] + + t = loader.get_template('shared_upload_link_email.html') + to_email_list = string2list(email) + for to_email in to_email_list: + # Add email to contacts. + mail_sended.send(sender=None, user=request.user.username, + email=to_email) + + c = { + 'email': request.user.username, + 'to_email': to_email, + 'shared_upload_link': shared_upload_link, + 'site_name': SITE_NAME, + } + + try: + send_mail(_(u'Your friend shared a upload link to you on Seafile'), + t.render(Context(c)), None, [to_email], + fail_silently=False) + except Exception, e: + logger.error(str(e)) + data = json.dumps({'error':_(u'Internal server error. Send failed.')}) + return HttpResponse(data, status=500, content_type=content_type) + + data = json.dumps({"msg": _(u'Successfully sent.')}) + return HttpResponse(data, status=200, content_type=content_type) + else: + return HttpResponseBadRequest(json.dumps(form.errors), + content_type=content_type) diff --git a/seahub/templates/repo.html b/seahub/templates/repo.html index 63e32a90ad..8a70f2e9e3 100644 --- a/seahub/templates/repo.html +++ b/seahub/templates/repo.html @@ -831,11 +831,11 @@ $('#add-new-file').click(function () { // share current dir $('#share-cur-dir').click(function() { - var op = $(this), name, aj_url, type; + var op = $(this), name, aj_urls, type; name = $('#cur-dir-name').html(); - aj_url = op.data('url'); + aj_urls = { 'link': op.data('url'), 'upload-link': op.data('upload-url') }; type = 'd'; - showSharePopup(op, name, aj_url, type, cur_path); + showSharePopup(op, name, aj_urls, type, cur_path); }); //select all or not @@ -1388,17 +1388,20 @@ $('.file-star', context).click(function() { //share $('.file-share, .dir-share', context).click(function() { - var op = $(this), name, aj_url, type; + var op = $(this), name, aj_urls, type; name = op.parents('tr').attr('data-name'); - aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name); + aj_urls = { + 'link': '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name), + 'upload-link': '{% url 'get_shared_upload_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name) + }; if (op.hasClass('dir-share')) { - aj_url += '&type=d'; + aj_urls['link'] += '&type=d'; type = 'd'; } else { type = 'f'; } - showSharePopup(op, name, aj_url, type, cur_path); + showSharePopup(op, name, aj_urls, type, cur_path); return false; }); diff --git a/seahub/templates/shared_upload_link_email.html b/seahub/templates/shared_upload_link_email.html new file mode 100644 index 0000000000..227f095382 --- /dev/null +++ b/seahub/templates/shared_upload_link_email.html @@ -0,0 +1,11 @@ +{% load i18n %}{% autoescape off %} +{% blocktrans %}You're receiving this e-mail because {{ email }} is sharing an upload link to you on {{ site_name }}.{% endblocktrans%} + +{% trans "Please go to the following page and upload your file:" %} +{{ shared_upload_link }} + +{% trans "Thanks for using our site!" %} + +{% blocktrans %}The {{ site_name }} team{% endblocktrans %} + +{% endautoescape %} diff --git a/seahub/templates/snippets/file_share_popup.html b/seahub/templates/snippets/file_share_popup.html index f84377614c..21d84cb1a4 100644 --- a/seahub/templates/snippets/file_share_popup.html +++ b/seahub/templates/snippets/file_share_popup.html @@ -4,6 +4,7 @@
+ + {% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}
diff --git a/seahub/templates/snippets/repo_dir_data.html b/seahub/templates/snippets/repo_dir_data.html index 25e8096eab..6118ae559e 100644 --- a/seahub/templates/snippets/repo_dir_data.html +++ b/seahub/templates/snippets/repo_dir_data.html @@ -22,7 +22,7 @@ {% if path != '/' %} {% if not repo.encrypted %} - + {% endif %} {% endif %}
diff --git a/seahub/templates/snippets/repo_dirents.html b/seahub/templates/snippets/repo_dirents.html index 8ac4608a51..30f8bc82b5 100644 --- a/seahub/templates/snippets/repo_dirents.html +++ b/seahub/templates/snippets/repo_dirents.html @@ -23,7 +23,7 @@
{% trans 'Download' %} {% if not repo.encrypted %} - {% trans "Share" %} + {% trans "Share" %} {% endif %}
{% if user_perm == 'rw' %} diff --git a/seahub/templates/snippets/shared_link_js.html b/seahub/templates/snippets/shared_link_js.html index a2f4fb84db..1a133d88fb 100644 --- a/seahub/templates/snippets/shared_link_js.html +++ b/seahub/templates/snippets/shared_link_js.html @@ -8,7 +8,7 @@ share_list.push({value: contact_email, label: contact_email}); contacts.push({value:contact_email, avatar:'{% avatar contact.contact_email 16 %}'}); {% endfor %} -function showSharePopup(op, name, aj_url, type, cur_path) { +function showSharePopup(op, name, aj_urls, type, cur_path) { var path; if (op.attr('id') == 'share-cur-dir') { path = cur_path.substr(0, cur_path.length - 1); // rm the last '/' as seafile_api treats '/xx' and '/xx/' as different @@ -24,6 +24,7 @@ function showSharePopup(op, name, aj_url, type, cur_path) { $('#private-share-tab, #private-share').remove(); } else { $('#syncable-share-tab, #syncable-share').remove(); + $('#upload-link-tab').remove(); } $("#file-share-tabs").tabs(); @@ -40,9 +41,28 @@ function showSharePopup(op, name, aj_url, type, cur_path) { $('#gen-link-btn').removeClass('hide'); $('#share-link-body').addClass('hide'); } - $('#gen-link-btn').data('url', aj_url).data('obj', op); + $('#gen-link-btn').data('url', aj_urls['link']).data('obj', op); $('#rm-shared-link').data('obj', op); + // share upload link + // files can only be uploaded to directory + if (type == 'd') { + if (op.data('upload-link')) { + $('#gen-upload-link-btn').addClass('hide'); + $('#share-upload-link-body').removeClass('hide'); + var link = op.data('upload-link'); + $('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(link); + $('#main').append('

' + link + '

'); + $('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25}); + $('#linkwidth').remove(); + } else { + $('#gen-upload-link-btn').removeClass('hide'); + $('#share-upload-link-body').addClass('hide'); + } + $('#gen-upload-link-btn').data('url', aj_urls['upload-link']).data('obj', op); + $('#rm-shared-upload-link').data('obj', op); + } + // 'private share' for file if ($('#private-share').length == 1) { $('#private-share-tab a').click(function() { @@ -221,3 +241,120 @@ $('#rm-shared-link').click(function() { } }); }); + +$('#shared-upload-link-text').click(function() { + $(this).select(); +}); + +$('#send-upload-link').click(function() { + $(this).addClass('hide'); + $('#rm-shared-upload-link').addClass('hide'); + var input = $('#upload-link-send-input'); + input.css({'width': $('#upload-link-share').width() - parseInt(input.css('padding-left')) - parseInt(input.css('padding-right')) - parseInt(input.css('border-left-width')) - parseInt(input.css('border-right-width'))}); + $('#upload-link-send-form').removeClass('hide'); + addAutocomplete('#upload-link-send-input', '#upload-link-send-form', share_list); +}); + +$("#upload-link-send-form .cancel").click(function() { + $('#upload-link-send-form, #send-upload-link, #rm-shared-upload-link').toggleClass('hide'); +}); + +$("#upload-link-send-form").submit(function(event) { + var form = $(this), + shared_upload_link = form.children('input[name="shared_upload_link"]').val(), + email = $.trim(form.children('textarea[name="email"]').val()), + submit_btn = form.children('input[type="submit"]'); + + if (!email) { + apply_form_error('upload-link-send-form', '{% trans "Please input at least an email." %}'); + return false; + } + + disable(submit_btn); + $('#upload-link-send-form .error').addClass('hide'); + $('#upload-sending').removeClass('hide'); + + $.ajax({ + type: "POST", + url: "{% url 'send_shared_upload_link' %}", + dataType: 'json', + cache: false, + beforeSend: prepareCSRFToken, + data: {shared_upload_link: shared_upload_link, email: email}, + success: function(data) { + $.modal.close(); + feedback(data['msg'], "success"); + }, + error: function(xhr, textStatus, errorThrown) { + $('#upload-sending').addClass('hide'); + enable(submit_btn); + var err_str = ''; + if (xhr.responseText) { + var err = jQuery.parseJSON(xhr.responseText); + if (err.error) { + err_str = err.error; + } else { + for (var i in err) { + err_str += err[i]; + } + } + } else { + err_str = '{% trans "Failed. Please check the network." %}'; + } + apply_form_error('upload-link-send-form', err_str); + } + }); + return false; +}); + +$('#gen-upload-link-btn').click(function() { + var gen_upload_link_btn = $(this), + obj = gen_upload_link_btn.data('obj'); + + $.ajax({ + url: gen_upload_link_btn.data('url'), + dataType: 'json', + cache: false, + success: function(data) { + var upload_link = data['shared_upload_link']; + gen_upload_link_btn.addClass('hide'); + $('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(upload_link); + $('#main').append('

' + upload_link + '

'); + $('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25}); + $('#linkwidth').remove(); + $('#share-upload-link-body').removeClass('hide'); + obj.data('upload-link', upload_link).data('upload-token', data['token']); + }, + error: function(xhr, textStatus, errorThrown) { + if (xhr.responseText) { + feedback(jQuery.parseJSON(xhr.responseText).error, 'error'); + } else { + feedback("{% trans "Failed. Please check the network." %}", 'error'); + } + } + }); + return false; +}); + +$('#rm-shared-upload-link').click(function() { + var obj = $(this).data('obj'), + token = obj.data('upload-token'); + + $.ajax({ + url: '{% url 'remove_shared_upload_link' %}?t=' + token, + dataType: 'json', + cache: false, + success: function(data) { + $('#share-upload-link-body').addClass('hide'); + $('#gen-upload-link-btn').removeClass('hide'); + obj.data('upload-link', '').data('upload-token', ''); + }, + error: function(xhr, textStatus, errorThrown) { + if (xhr.responseText) { + feedback(jQuery.parseJSON(xhr.responseText).error, 'error'); + } else { + feedback("{% trans "Failed. Please check the network." %}", 'error'); + } + } + }); +}); diff --git a/seahub/templates/view_file_base.html b/seahub/templates/view_file_base.html index e28e0ddd54..7a87f1287b 100644 --- a/seahub/templates/view_file_base.html +++ b/seahub/templates/view_file_base.html @@ -97,9 +97,9 @@ + + + + + + +{% endblock %} diff --git a/seahub/urls.py b/seahub/urls.py index 24ef3b84bb..bef15d14db 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -92,6 +92,7 @@ urlpatterns = patterns('', url(r'^f/(?P[a-f0-9]{10})/$', view_shared_file, name='view_shared_file'), url(r'^d/(?P[a-f0-9]{10})/$', view_shared_dir, name='view_shared_dir'), url(r'^d/(?P[a-f0-9]{10})/files/$', view_file_via_shared_dir, name='view_file_via_shared_dir'), + url(r'^u/d/(?P[a-f0-9]{10})/$', view_shared_upload_dir, name='view_shared_upload_dir'), ### Misc ### (r'^file_upload_progress_page/$', file_upload_progress_page), diff --git a/seahub/utils/__init__.py b/seahub/utils/__init__.py index d8c32a829d..37078e233e 100644 --- a/seahub/utils/__init__.py +++ b/seahub/utils/__init__.py @@ -835,6 +835,13 @@ def gen_shared_link(token, s_type): else: return '%s/d/%s/' % (service_url, token) +def gen_shared_upload_link(token): + service_url = get_service_url() + assert service_url is not None + + service_url = service_url.rstrip('/') + return '%s/u/d/%s/' % (service_url, token) + def show_delete_days(request): if request.method == 'GET': days_str = request.GET.get('days', '') diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py index 2ea3154aaf..b7d38d23d8 100644 --- a/seahub/views/__init__.py +++ b/seahub/views/__init__.py @@ -44,7 +44,8 @@ from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_repos, get_emailusers, \ set_repo_history_limit, \ get_commit, MAX_DOWNLOAD_DIR_SIZE, CALC_SHARE_USAGE, count_emailusers, \ count_inner_pub_repos, unset_inner_pub_repo, get_user_quota_usage, \ - get_user_share_usage, send_message + get_user_share_usage, send_message, \ + MAX_UPLOAD_FILE_SIZE from seaserv import seafile_api from pysearpc import SearpcError @@ -63,13 +64,13 @@ from seahub.group.signals import grpmsg_added from seahub.notifications.models import UserNotification from seahub.options.models import UserOptions, CryptoOptionNotSetError from seahub.profile.models import Profile -from seahub.share.models import FileShare, PrivateFileDirShare +from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare from seahub.forms import AddUserForm, RepoCreateForm, \ RepoPassowrdForm, SharedRepoCreateForm,\ SetUserQuotaForm, RepoSettingForm from seahub.signals import repo_created, repo_deleted from seahub.utils import render_permission_error, render_error, list_to_string, \ - get_httpserver_root, get_ccnetapplet_root, \ + get_httpserver_root, get_ccnetapplet_root, gen_shared_upload_link, \ gen_dir_share_link, gen_file_share_link, get_repo_last_modify, \ calculate_repos_last_modify, get_file_type_and_ext, get_user_repos, \ EMPTY_SHA1, normalize_file_path, \ @@ -221,10 +222,12 @@ def get_repo_dirents(request, repo_id, commit, path, offset=-1, limit=-1): last_modified_info = get_dir_files_last_modified(repo_id, path) fileshares = FileShare.objects.filter(repo_id=repo_id).filter(username=request.user.username) + uploadlinks = UploadLinkShare.objects.filter(repo_id=repo_id).filter(username=request.user.username) for dirent in dirs: dirent.last_modified = last_modified_info.get(dirent.obj_name, 0) dirent.sharelink = '' + dirent.uploadlink = '' if stat.S_ISDIR(dirent.props.mode): dpath = os.path.join(path, dirent.obj_name) if dpath[-1] != '/': @@ -234,6 +237,11 @@ def get_repo_dirents(request, repo_id, commit, path, offset=-1, limit=-1): dirent.sharelink = gen_dir_share_link(share.token) dirent.sharetoken = share.token break + for link in uploadlinks: + if dpath == link.path: + dirent.uploadlink = gen_shared_upload_link(link.token) + dirent.uploadtoken = link.token + break dir_list.append(dirent) else: file_list.append(dirent) @@ -1676,7 +1684,45 @@ def view_shared_dir(request, token): 'dir_list': dir_list, 'zipped': zipped, }, context_instance=RequestContext(request)) - + +def view_shared_upload_dir(request, token): + assert token is not None # Checked by URLconf + + try: + uploadlink = UploadLinkShare.objects.get(token=token) + except UploadLinkShare.DoesNotExist: + raise Http404 + + username = uploadlink.username + repo_id = uploadlink.repo_id + path = uploadlink.path + dir_name = os.path.basename(path[:-1]) + + repo = get_repo(repo_id) + if not repo: + raise Http404 + + uploadlink.view_cnt = F('view_cnt') + 1 + uploadlink.save() + + max_upload_file_size = MAX_UPLOAD_FILE_SIZE + no_quota = True if seaserv.check_quota(repo_id) < 0 else False + + token = seafile_api.get_httpserver_access_token(repo_id, 'dummy', + 'upload', request.user.username) + ajax_upload_url = gen_file_upload_url(token, 'upload-api').replace('api', 'aj') + + return render_to_response('view_shared_upload_dir.html', { + 'repo': repo, + 'token': token, + 'path': path, + 'username': username, + 'dir_name': dir_name, + 'max_upload_file_size': max_upload_file_size, + 'no_quota': no_quota, + 'ajax_upload_url': ajax_upload_url + }, context_instance=RequestContext(request)) + def demo(request): """ Login as demo account. diff --git a/seahub/views/ajax.py b/seahub/views/ajax.py index 2f4ca9af08..e639db603d 100644 --- a/seahub/views/ajax.py +++ b/seahub/views/ajax.py @@ -20,7 +20,8 @@ from seahub.contacts.models import Contact from seahub.forms import RepoNewDirentForm, RepoRenameDirentForm from seahub.options.models import UserOptions, CryptoOptionNotSetError from seahub.views import get_repo_dirents -from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link +from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link, \ + get_uploadlink, get_dir_shared_upload_link import seahub.settings as settings from seahub.utils import check_filename_with_rename, EMPTY_SHA1, gen_block_get_url from seahub.utils.star import star_file, unstar_file @@ -229,6 +230,8 @@ def list_dir(request, repo_id): zipped = get_nav_path(path, repo.name) fileshare = get_fileshare(repo.id, username, path) dir_shared_link = get_dir_share_link(fileshare) + uploadlink = get_uploadlink(repo.id, username, path) + dir_shared_upload_link = get_dir_shared_upload_link(uploadlink) ctx = { 'repo': repo, @@ -238,6 +241,8 @@ def list_dir(request, repo_id): 'server_crypto': server_crypto, 'fileshare': fileshare, 'dir_shared_link': dir_shared_link, + 'uploadlink': uploadlink, + 'dir_shared_upload_link': dir_shared_upload_link, 'dir_list': dir_list, 'file_list': file_list, 'dirent_more': dirent_more, diff --git a/seahub/views/repo.py b/seahub/views/repo.py index 6344b84d6c..da7efb881f 100644 --- a/seahub/views/repo.py +++ b/seahub/views/repo.py @@ -15,12 +15,12 @@ from seahub.auth.decorators import login_required from seahub.contacts.models import Contact from seahub.forms import RepoPassowrdForm from seahub.options.models import UserOptions, CryptoOptionNotSetError -from seahub.share.models import FileShare +from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare from seahub.views import gen_path_link, get_user_permission, get_repo_dirents, \ get_unencry_rw_repos_by_user from seahub.utils import get_ccnetapplet_root, gen_file_upload_url, \ - get_httpserver_root, gen_dir_share_link + get_httpserver_root, gen_dir_share_link, gen_shared_upload_link from seahub.settings import ENABLE_SUB_LIBRARY # Get an instance of a logger @@ -169,6 +169,22 @@ def get_dir_share_link(fileshare): dir_shared_link = '' return dir_shared_link +def get_uploadlink(repo_id, username, path): + if path == '/': # no shared upload link for root dir + return None + + l = UploadLinkShare.objects.filter(repo_id=repo_id).filter( + username=username).filter(path=path) + return l[0] if len(l) > 0 else None + +def get_dir_shared_upload_link(uploadlink): + # dir shared upload link + if uploadlink: + dir_shared_upload_link = gen_shared_upload_link(uploadlink.token) + else: + dir_shared_upload_link = '' + return dir_shared_upload_link + def render_repo(request, repo): """Steps to show repo page: If user has permission to view repo @@ -245,6 +261,8 @@ def render_repo(request, repo): ajax_update_url = get_ajax_update_url(request, repo.id) fileshare = get_fileshare(repo.id, username, path) dir_shared_link = get_dir_share_link(fileshare) + uploadlink = get_uploadlink(repo.id, username, path) + dir_shared_upload_link = get_dir_shared_upload_link(uploadlink) return render_to_response('repo.html', { 'repo': repo, @@ -276,6 +294,8 @@ def render_repo(request, repo): 'contacts': contacts, 'fileshare': fileshare, 'dir_shared_link': dir_shared_link, + 'uploadlink': uploadlink, + 'dir_shared_upload_link': dir_shared_upload_link, 'search_repo_id': search_repo_id, 'ENABLE_SUB_LIBRARY': ENABLE_SUB_LIBRARY, 'server_crypto': server_crypto,