diff --git a/forms.py b/forms.py index 86fb713d42..aad63cad3a 100644 --- a/forms.py +++ b/forms.py @@ -40,17 +40,6 @@ class AddUserForm(forms.Form): raise forms.ValidationError(_("The two password fields didn't match.")) return self.cleaned_data -class FileLinkShareForm(forms.Form): - """ - Form for sharing file shared link to emails. - """ - - email = forms.CharField(max_length=512, error_messages={ - 'required': _("Email is required"), - 'max_length': _("Email is not longer than 512 characters"), - }) - file_shared_link = forms.CharField() - class FileCommentForm(forms.Form): """ Form for leave comments on file. diff --git a/group/templates/group/group_info.html b/group/templates/group/group_info.html index 5f29c0f056..c1fafef9ca 100644 --- a/group/templates/group/group_info.html +++ b/group/templates/group/group_info.html @@ -100,7 +100,7 @@ {% trans {% endif %} {% if is_staff or repo.share_from_me %} - {% trans + {% trans {% endif %} diff --git a/share/forms.py b/share/forms.py index f4738f48e4..c7a093748a 100644 --- a/share/forms.py +++ b/share/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import ugettext_lazy as _ class RepoShareForm(forms.Form): """ @@ -8,3 +9,15 @@ class RepoShareForm(forms.Form): email_or_group = forms.CharField(max_length=512) repo_id = forms.CharField(max_length=36) permission = forms.ChoiceField(choices=(('rw', 'read-write'), ('r', 'read-only'))) + +class FileLinkShareForm(forms.Form): + """ + Form for sharing file shared link to emails. + """ + + email = forms.CharField(max_length=512, error_messages={ + 'required': _("Email is required"), + 'max_length': _("Email is not longer than 512 characters"), + }) + file_shared_link = forms.CharField() + diff --git a/share/templates/repo/share_admin.html b/share/templates/repo/share_admin.html index acb40c939c..f46f7c87b6 100644 --- a/share/templates/repo/share_admin.html +++ b/share/templates/repo/share_admin.html @@ -2,7 +2,7 @@ {% load seahub_tags i18n %} {% load url from future %} -{% block nav_shareadmin_class %}class="cur"{% endblock %} +{% block nav_share_class %}class="cur"{% endblock %} {% if org %} {% block title_panel %} @@ -53,10 +53,10 @@ {{ repo.props.repo_desc }} {% if repo.props.share_type == 'group' %} - {% trans "Unshare"%} + {% trans "Unshare"%} {% endif %} {% if repo.props.share_type == 'personal' %} - {% trans "Unshare"%} + {% trans "Unshare"%} {% endif %} {% if repo.props.share_type == 'public' %} {% if not org %} @@ -92,7 +92,7 @@ {{ fs.view_cnt }} {% trans "View" %} - {% trans "Remove"%} + {% trans "Remove"%} {% endfor %} diff --git a/share/urls.py b/share/urls.py index 424b5860db..a2fe63c9b1 100644 --- a/share/urls.py +++ b/share/urls.py @@ -3,8 +3,15 @@ from django.conf.urls.defaults import * from views import * urlpatterns = patterns('', + url(r'^$', share_admin, name='share_admin'), url(r'^add/$', share_repo, name='share_repo'), + url(r'^remove/$', repo_remove_share, name='repo_remove_share'), url('^remove/(?P[^/]{24,24})/$', remove_anonymous_share, name='remove_anonymous_share'), - url('^(?P[^/]{24,24})/$', anonymous_share_confirm, name='anonymous_share_confirm'), + + url(r'^link/get/$', get_shared_link, name='get_shared_link'), + url(r'^link/remove/$', remove_shared_link, name='remove_shared_link'), + url(r'^link/send/$', send_shared_link, name='send_shared_link'), + + url('^(?P[^/]{24})/$', anonymous_share_confirm, name='anonymous_share_confirm'), url(r'^permission_admin/$', share_permission_admin, name='share_permission_admin'), ) diff --git a/share/views.py b/share/views.py index 90503383f1..c544621a88 100644 --- a/share/views.py +++ b/share/views.py @@ -14,16 +14,18 @@ from django.contrib.sites.models import Site, RequestSite from pysearpc import SearpcError from seaserv import seafserv_threaded_rpc, get_repo, ccnet_rpc, \ ccnet_threaded_rpc, get_personal_groups, list_personal_shared_repos, \ - is_personal_repo + is_personal_repo, check_group_staff, is_org_group, get_org_id_by_group, \ + del_org_group_repo -from forms import RepoShareForm +from forms import RepoShareForm, FileLinkShareForm from models import AnonymousShare from settings import ANONYMOUS_SHARE_COOKIE_TIMEOUT from tokens import anon_share_token_generator from seahub.contacts.signals import mail_sended from seahub.share.models import FileShare from seahub.views import validate_owner, is_registered_user -from seahub.utils import render_permission_error, string2list +from seahub.utils import render_permission_error, string2list, render_error, \ + gen_token try: from seahub.settings import CLOUD_MODE @@ -133,6 +135,51 @@ def share_repo(request): return HttpResponseRedirect(reverse('myhome')) +@login_required +def repo_remove_share(request): + """ + If repo is shared from one person to another person, only these two peson + 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. + """ + repo_id = request.GET.get('repo_id', '') + group_id = request.GET.get('gid', '') + from_email = request.GET.get('from', '') + + # if request params don't have 'gid', then remove repos that share to + # to other person; else, remove repos that share to groups + if not group_id: + to_email = request.GET.get('to', '') + if request.user.username != from_email and \ + request.user.username != to_email: + return render_permission_error(request, _(u'Failed to remove share')) + seafserv_threaded_rpc.remove_share(repo_id, from_email, to_email) + else: + try: + group_id_int = int(group_id) + except: + return render_error(request, _(u'group id is not valid')) + + if not check_group_staff(group_id_int, request.user) \ + and request.user.username != from_email: + return render_permission_error(request, _(u'Failed to remove share')) + + if is_org_group(group_id_int): + org_id = get_org_id_by_group(group_id_int) + del_org_group_repo(repo_id, org_id, group_id_int) + else: + from group.views import group_unshare_repo + group_unshare_repo(request, repo_id, group_id_int, from_email) + + messages.success(request, _('Successfully removed share')) + + next = request.META.get('HTTP_REFERER', None) + if not next: + next = settings.SITE_ROOT + + return HttpResponseRedirect(next) + @login_required def share_admin(request): """ @@ -320,3 +367,111 @@ def remove_anonymous_share(request, token): return HttpResponseRedirect(next) +@login_required +def get_shared_link(request): + """ + Handle ajax request to generate file shared link. + """ + if not request.is_ajax(): + raise Http404 + + content_type = 'application/json; charset=utf-8' + + repo_id = request.GET.get('repo_id') + obj_id = request.GET.get('obj_id') + path = request.GET.get('p', '/') + if path[-1] == '/': + path = path[:-1] + + l = FileShare.objects.filter(repo_id=repo_id).filter( + username=request.user.username).filter(path=path) + if len(l) > 0: + fileshare = l[0] + token = fileshare.token + else: + token = gen_token(max_length=10) + + fs = FileShare() + fs.username = request.user.username + fs.repo_id = repo_id + fs.path = path + fs.token = token + + try: + fs.save() + except IntegrityError, e: + err = _('Failed to get shared link, please retry.') + data = json.dumps([{'error': err}]) + return HttpResponse(data, status=500, content_type=content_type) + + data = json.dumps([{'token': token}]) + return HttpResponse(data, status=200, content_type=content_type) + +@login_required +def remove_shared_link(request): + """ + Handle request to remove file shared link. + """ + token = request.GET.get('t', '') + + if not request.is_ajax(): + FileShare.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' + + FileShare.objects.filter(token=token).delete() + + msg = _('Removed successfully') + data = json.dumps([{'msg': msg}]) + return HttpResponse(data, status=200, content_type=content_type) + +@login_required +def send_shared_link(request): + """ + Handle ajax post request to send file shared link. + """ + if not request.is_ajax() and not request.method == 'POST': + raise Http404 + + result = {} + content_type = 'application/json; charset=utf-8' + + form = FileLinkShareForm(request.POST) + if form.is_valid(): + email = form.cleaned_data['email'] + file_shared_link = form.cleaned_data['file_shared_link'] + + t = loader.get_template('shared_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, + 'file_shared_link': file_shared_link, + } + + try: + send_mail(_(u'Your friend sharing a file to you on Seafile'), + t.render(Context(c)), None, [to_email], + fail_silently=False) + except: + data = json.dumps({'error':_(u'Failed to send mail')}) + return HttpResponse(data, status=500, content_type=content_type) + + data = json.dumps("success") + return HttpResponse(data, status=200, content_type=content_type) + else: + return HttpResponseBadRequest(json.dumps(form.errors), + content_type=content_type) + diff --git a/templates/myhome_base.html b/templates/myhome_base.html index 6fa9159006..ec189bd06c 100644 --- a/templates/myhome_base.html +++ b/templates/myhome_base.html @@ -11,7 +11,7 @@ {% trans "Groups" %}
  • - {% trans "Share" %} + {% trans "Share" %}
  • {% trans "Contacts" %} diff --git a/templates/repo_view_file.html b/templates/repo_view_file.html index 1708fb886c..5a5bc523ca 100644 --- a/templates/repo_view_file.html +++ b/templates/repo_view_file.html @@ -69,9 +69,9 @@ {% if not view_history %}
    - + - + {% if is_starred %} {% else %} @@ -135,8 +135,8 @@ {% if not view_history %}