mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-08 02:23:44 +00:00
Merge branch '5.0'
Conflicts: seahub/api2/urls.py seahub/api2/views.py seahub/group/templates/group/group_discuss.html seahub/options/models.py seahub/templates/repo_folder_perm.html seahub/templates/repo_share_manage.html seahub/templates/snippets/shared_link_js.html seahub/test_utils.py
This commit is contained in:
commit
ec9be6975d
@ -300,6 +300,9 @@ td, th { padding:5px 3px; word-wrap:break-word; border-bottom:1px solid #eee; }
|
|||||||
td { color: #333; font-size:14px; }
|
td { color: #333; font-size:14px; }
|
||||||
table img { vertical-align:middle; }
|
table img { vertical-align:middle; }
|
||||||
p { margin:0.5em 0; }
|
p { margin:0.5em 0; }
|
||||||
|
:focus {/* to overwrite user agent stylesheet */
|
||||||
|
outline:none;
|
||||||
|
}
|
||||||
|
|
||||||
/********** common class ***********/
|
/********** common class ***********/
|
||||||
.hl { background-color: #f8f8f8; }/*highlight*/
|
.hl { background-color: #f8f8f8; }/*highlight*/
|
||||||
|
@ -218,17 +218,6 @@ $('#logout').click(function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if ($.browser.mozilla || $.browser.msie) {
|
|
||||||
$('a').focus(function() {
|
|
||||||
$(this).blur();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if ($.browser.msie) {
|
|
||||||
$('button, input[type="checkbox"], input[type="radio"], input[type="submit"]').focus(function() {
|
|
||||||
$(this).blur();
|
|
||||||
});
|
|
||||||
$('.search-input').css({'line-height':$('.search-input').css('height')});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add confirm to an operation, using a popup
|
* add confirm to an operation, using a popup
|
||||||
|
169
media/js/jq.min.js
vendored
169
media/js/jq.min.js
vendored
File diff suppressed because one or more lines are too long
5
media/js/jquery-1.12.1.min.js
vendored
Normal file
5
media/js/jquery-1.12.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -76,7 +76,6 @@ class Account(APIView):
|
|||||||
profile.intro = note
|
profile.intro = note
|
||||||
|
|
||||||
profile.save()
|
profile.save()
|
||||||
refresh_profile_cache(email)
|
|
||||||
|
|
||||||
def _update_account_quota(self, request, email):
|
def _update_account_quota(self, request, email):
|
||||||
storage = request.data.get("storage", None)
|
storage = request.data.get("storage", None)
|
||||||
|
@ -52,13 +52,14 @@ urlpatterns = patterns('',
|
|||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/detail/$', FileDetailView.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/detail/$', FileDetailView.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/history/$', FileHistory.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/history/$', FileHistory.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/revision/$', FileRevision.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/revision/$', FileRevision.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/revert/$', FileRevert.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/revert/$', FileRevert.as_view(), name='api2-file-revert'),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/shared-link/$', FileSharedLinkView.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/file/shared-link/$', FileSharedLinkView.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='DirView'),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='DirView'),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/sub_repo/$', DirSubRepoView.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/sub_repo/$', DirSubRepoView.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/share/$', DirShareView.as_view()),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/share/$', DirShareView.as_view()),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/shared_items/$', DirSharedItemsEndpoint.as_view(), name="api2-dir-shared-items"),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/shared_items/$', DirSharedItemsEndpoint.as_view(), name="api2-dir-shared-items"),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/download/$', DirDownloadView.as_view(), name='api2-dir-download'),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/download/$', DirDownloadView.as_view(), name='api2-dir-download'),
|
||||||
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/dir/revert/$', DirRevert.as_view(), name='api2-dir-revert'),
|
||||||
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/thumbnail/$', ThumbnailView.as_view(), name='api2-thumbnail'),
|
url(r'^repos/(?P<repo_id>[-0-9-a-f]{36})/thumbnail/$', ThumbnailView.as_view(), name='api2-thumbnail'),
|
||||||
url(r'^starredfiles/', StarredFileView.as_view(), name='starredfiles'),
|
url(r'^starredfiles/', StarredFileView.as_view(), name='starredfiles'),
|
||||||
url(r'^devices/', DevicesView.as_view(), name='api2-devices'),
|
url(r'^devices/', DevicesView.as_view(), name='api2-devices'),
|
||||||
|
@ -1861,6 +1861,7 @@ class OwaFileView(APIView):
|
|||||||
send_file_access_msg(request, repo, path, 'api')
|
send_file_access_msg(request, repo, path, 'api')
|
||||||
return Response(wopi_dict)
|
return Response(wopi_dict)
|
||||||
|
|
||||||
|
|
||||||
class DevicesView(APIView):
|
class DevicesView(APIView):
|
||||||
"""List user devices"""
|
"""List user devices"""
|
||||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
@ -1894,6 +1895,7 @@ class DevicesView(APIView):
|
|||||||
|
|
||||||
return Response({'success': True})
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
class FileView(APIView):
|
class FileView(APIView):
|
||||||
"""
|
"""
|
||||||
Support uniform interface for file related operations,
|
Support uniform interface for file related operations,
|
||||||
@ -2268,38 +2270,44 @@ class FileDetailView(APIView):
|
|||||||
content_type=json_content_type)
|
content_type=json_content_type)
|
||||||
|
|
||||||
class FileRevert(APIView):
|
class FileRevert(APIView):
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
throttle_classes = (UserRateThrottle, )
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
def put(self, request, repo_id, format=None):
|
def put(self, request, repo_id, format=None):
|
||||||
path = request.data.get('p', '')
|
path = request.data.get('p', None)
|
||||||
|
commit_id = request.data.get('commit_id', None)
|
||||||
|
|
||||||
if not path:
|
if not path:
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, 'Path is missing.')
|
error_msg = 'path invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not commit_id:
|
||||||
|
error_msg = 'commit_id invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not seafile_api.get_repo(repo_id):
|
||||||
|
error_msg = 'library %s not found.' % repo_id
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if not seafile_api.get_file_id_by_commit_and_path(repo_id, commit_id, path):
|
||||||
|
error_msg = 'file %s not found.' % path
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if check_folder_permission(request, repo_id, '/') != 'rw':
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
is_locked, locked_by_me = check_file_lock(repo_id, path, username)
|
|
||||||
if (is_locked, locked_by_me) == (None, None):
|
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Check file lock error')
|
|
||||||
|
|
||||||
if is_locked and not locked_by_me:
|
|
||||||
return api_error(status.HTTP_403_FORBIDDEN, 'File is locked')
|
|
||||||
|
|
||||||
parent_dir = os.path.dirname(path)
|
|
||||||
if check_folder_permission(request, repo_id, parent_dir) != 'rw':
|
|
||||||
return api_error(status.HTTP_403_FORBIDDEN,
|
|
||||||
'You do not have permission to access this folder.')
|
|
||||||
|
|
||||||
path = unquote(path.encode('utf-8'))
|
|
||||||
commit_id = unquote(request.data.get('commit_id', '').encode('utf-8'))
|
|
||||||
try:
|
try:
|
||||||
ret = seafserv_threaded_rpc.revert_file(repo_id, commit_id,
|
seafile_api.revert_file(repo_id, commit_id, path, username)
|
||||||
path, username)
|
|
||||||
except SearpcError as e:
|
except SearpcError as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, "Internal error")
|
error_msg = 'Internal Server Error'
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
||||||
|
|
||||||
return HttpResponse(json.dumps({"ret": ret}), status=200, content_type=json_content_type)
|
|
||||||
|
|
||||||
class FileRevision(APIView):
|
class FileRevision(APIView):
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
@ -2698,6 +2706,45 @@ class DirDownloadView(APIView):
|
|||||||
return HttpResponse(json.dumps(redirect_url), status=200,
|
return HttpResponse(json.dumps(redirect_url), status=200,
|
||||||
content_type=json_content_type)
|
content_type=json_content_type)
|
||||||
|
|
||||||
|
class DirRevert(APIView):
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
throttle_classes = (UserRateThrottle, )
|
||||||
|
|
||||||
|
def put(self, request, repo_id):
|
||||||
|
path = request.data.get('p', None)
|
||||||
|
commit_id = request.data.get('commit_id', None)
|
||||||
|
|
||||||
|
if not path:
|
||||||
|
error_msg = 'path invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not commit_id:
|
||||||
|
error_msg = 'commit_id invalid.'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
if not seafile_api.get_repo(repo_id):
|
||||||
|
error_msg = 'library %s not found.' % repo_id
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if not seafile_api.get_dir_id_by_commit_and_path(repo_id, commit_id, path):
|
||||||
|
error_msg = 'folder %s not found.' % path
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if check_folder_permission(request, repo_id, '/') != 'rw':
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
try:
|
||||||
|
seafile_api.revert_dir(repo_id, commit_id, path, username)
|
||||||
|
except SearpcError as e:
|
||||||
|
logger.error(e)
|
||||||
|
error_msg = 'Internal Server Error'
|
||||||
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
||||||
|
|
||||||
class DirShareView(APIView):
|
class DirShareView(APIView):
|
||||||
authentication_classes = (TokenAuthentication, )
|
authentication_classes = (TokenAuthentication, )
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
|
@ -71,7 +71,7 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
|
|||||||
if autoescape and not safe_input:
|
if autoescape and not safe_input:
|
||||||
lead, trail = escape(lead), escape(trail)
|
lead, trail = escape(lead), escape(trail)
|
||||||
url, trimmed = escape(url), escape(trimmed)
|
url, trimmed = escape(url), escape(trimmed)
|
||||||
middle = '<a target="_blank" href="%s"%s>%s</a>' % (url, nofollow_attr, trimmed)
|
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr, trimmed)
|
||||||
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
|
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
|
||||||
else:
|
else:
|
||||||
if safe_input:
|
if safe_input:
|
||||||
|
@ -187,12 +187,18 @@ class UserOptionsManager(models.Manager):
|
|||||||
- `self`:
|
- `self`:
|
||||||
- `username`:
|
- `username`:
|
||||||
"""
|
"""
|
||||||
try:
|
user_options = super(UserOptionsManager, self).filter(
|
||||||
user_option = super(UserOptionsManager, self).get(
|
email=username, option_key=KEY_DEFAULT_REPO)
|
||||||
email=username, option_key=KEY_DEFAULT_REPO)
|
|
||||||
return user_option.option_val
|
if len(user_options) == 0:
|
||||||
except UserOptions.DoesNotExist:
|
|
||||||
return None
|
return None
|
||||||
|
elif len(user_options) == 1:
|
||||||
|
return user_options[0].option_val
|
||||||
|
else:
|
||||||
|
for o in user_options[1: len(user_options)]:
|
||||||
|
o.delete()
|
||||||
|
|
||||||
|
return user_options[0].option_val
|
||||||
|
|
||||||
def passwd_change_required(self, username):
|
def passwd_change_required(self, username):
|
||||||
"""Check whether user need to change password.
|
"""Check whether user need to change password.
|
||||||
@ -211,10 +217,10 @@ class UserOptionsManager(models.Manager):
|
|||||||
def unset_force_passwd_change(self, username):
|
def unset_force_passwd_change(self, username):
|
||||||
return self.unset_user_option(username, KEY_FORCE_PASSWD_CHANGE)
|
return self.unset_user_option(username, KEY_FORCE_PASSWD_CHANGE)
|
||||||
|
|
||||||
|
|
||||||
class UserOptions(models.Model):
|
class UserOptions(models.Model):
|
||||||
email = LowerCaseCharField(max_length=255, db_index=True)
|
email = LowerCaseCharField(max_length=255, db_index=True)
|
||||||
option_key = models.CharField(max_length=50)
|
option_key = models.CharField(max_length=50)
|
||||||
option_val = models.CharField(max_length=50)
|
option_val = models.CharField(max_length=50)
|
||||||
|
|
||||||
objects = UserOptionsManager()
|
objects = UserOptionsManager()
|
||||||
|
|
||||||
|
@ -129,11 +129,19 @@ class DetailedProfile(models.Model):
|
|||||||
telephone = models.CharField(max_length=100)
|
telephone = models.CharField(max_length=100)
|
||||||
objects = DetailedProfileManager()
|
objects = DetailedProfileManager()
|
||||||
|
|
||||||
########## signal handler
|
|
||||||
|
########## signal handlers
|
||||||
|
from django.db.models.signals import post_save
|
||||||
|
from .utils import refresh_cache
|
||||||
|
|
||||||
@receiver(user_registered)
|
@receiver(user_registered)
|
||||||
def clean_email_id_cache(sender, **kwargs):
|
def clean_email_id_cache(sender, **kwargs):
|
||||||
from seahub.utils import normalize_cache_key
|
from seahub.utils import normalize_cache_key
|
||||||
|
|
||||||
user = kwargs['user']
|
user = kwargs['user']
|
||||||
key = normalize_cache_key(user.email, EMAIL_ID_CACHE_PREFIX)
|
key = normalize_cache_key(user.email, EMAIL_ID_CACHE_PREFIX)
|
||||||
cache.set(key, user.id, EMAIL_ID_CACHE_TIMEOUT)
|
cache.set(key, user.id, EMAIL_ID_CACHE_TIMEOUT)
|
||||||
|
|
||||||
|
@receiver(post_save, sender=Profile, dispatch_uid="update_nickname_cache")
|
||||||
|
def update_nickname_cache(sender, instance, **kwargs):
|
||||||
|
refresh_cache(instance.user)
|
||||||
|
@ -36,9 +36,7 @@ def edit_profile(request):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save(username=username)
|
form.save(username=username)
|
||||||
messages.success(request, _(u'Successfully edited profile.'))
|
messages.success(request, _(u'Successfully edited profile.'))
|
||||||
# refresh nickname cache
|
|
||||||
refresh_cache(request.user.username)
|
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse('edit_profile'))
|
return HttpResponseRedirect(reverse('edit_profile'))
|
||||||
else:
|
else:
|
||||||
messages.error(request, _(u'Failed to edit profile'))
|
messages.error(request, _(u'Failed to edit profile'))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% load seahub_tags avatar_tags group_avatar_tags i18n %}
|
{% load seahub_tags avatar_tags group_avatar_tags i18n staticfiles %}
|
||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
{% block info_bar_message %}
|
{% block info_bar_message %}
|
||||||
{% if request.user.is_authenticated and request.cur_note %}
|
{% if request.user.is_authenticated and request.cur_note %}
|
||||||
<div id="info-bar">
|
<div id="info-bar">
|
||||||
<p id="info-bar-info">{{ request.cur_note.message|urlize|url_target_blank }}</p>
|
<p id="info-bar-info">{{ request.cur_note.message|urlize }}</p>
|
||||||
<span class="close sf2-icon-x1 op-icon" data="{{ request.cur_note.id }}" title="{% trans "Close" %}"></span>
|
<span class="close sf2-icon-x1 op-icon" data="{{ request.cur_note.id }}" title="{% trans "Close" %}"></span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -149,7 +149,10 @@
|
|||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
</div><!-- wrapper -->
|
</div><!-- wrapper -->
|
||||||
|
|
||||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/jq.min.js?t=1398068110"></script>
|
<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery-1.12.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="{% static "scripts/lib/jquery.simplemodal.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static "scripts/lib/jquery.ui.tabs.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{{ MEDIA_URL }}js/jq.min.js"></script>
|
||||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/base.js?t=1404370380"></script>
|
<script type="text/javascript" src="{{ MEDIA_URL }}js/base.js?t=1404370380"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$.jstree._themes = '{{ MEDIA_URL }}js/themes/';
|
$.jstree._themes = '{{ MEDIA_URL }}js/themes/';
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
{% block info_bar_message %}
|
{% block info_bar_message %}
|
||||||
{% if request.user.is_authenticated and request.cur_note %}
|
{% if request.user.is_authenticated and request.cur_note %}
|
||||||
<div id="info-bar">
|
<div id="info-bar">
|
||||||
<p id="info-bar-info">{{ request.cur_note.message|urlize|url_target_blank }}</p>
|
<p id="info-bar-info">{{ request.cur_note.message|urlize }}</p>
|
||||||
<span class="close sf2-icon-x1 op-icon" title="{% trans "Close" %}"></span>
|
<span class="close sf2-icon-x1 op-icon" title="{% trans "Close" %}"></span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -125,12 +125,31 @@ var get_more_trash = function(current_scan_stat) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$('table').on("click", ".restore-file, .restore-dir", function() {
|
$('table').on("click", ".restore-file, .restore-dir", function() {
|
||||||
$('<form>', {
|
var _this = $(this),
|
||||||
"method": 'POST',
|
commit_id = _this.data('commit_id'),
|
||||||
"action": $(this).data('url'),
|
path = _this.data('path');
|
||||||
"html": '<input name="csrfmiddlewaretoken" value="' + getCookie('csrftoken') + '" type="hidden">'
|
|
||||||
}).appendTo(document.body).submit();
|
$.ajax({
|
||||||
|
url: _this.data('url'),
|
||||||
|
type: 'PUT',
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
data: {'commit_id': commit_id, 'p': path},
|
||||||
|
success: function(data) {
|
||||||
|
_this.closest('tr').remove();
|
||||||
|
feedback("{% trans "Success" %}", 'success');
|
||||||
|
},
|
||||||
|
error: function ajaxErrorHandler(xhr, textStatus, errorThrown) {
|
||||||
|
if (xhr.responseText) {
|
||||||
|
feedback($.parseJSON(xhr.responseText).error_msg, 'error');
|
||||||
|
} else {
|
||||||
|
feedback("{% trans "Failed. Please check the network." %}", 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ $('#add-file-popup .submit').click(function() {
|
|||||||
$.modal.close();
|
$.modal.close();
|
||||||
var files = '';
|
var files = '';
|
||||||
for (var i = 0, len = selected.length; i < len; i++) {
|
for (var i = 0, len = selected.length; i < len; i++) {
|
||||||
files += '<li class="item">' + '<img src="{{MEDIA_URL}}img/del.png" class="rm vam" data-index="' + i + '" /><span class="vam">' + selected[i].substr(selected[i].lastIndexOf('/') + 1) + '</span></li>';
|
files += '<li class="item">' + '<img src="{{MEDIA_URL}}img/del.png" class="rm vam" data-index="' + i + '" /><span class="vam">' + HTMLescape(selected[i].substr(selected[i].lastIndexOf('/') + 1)) + '</span></li>';
|
||||||
}
|
}
|
||||||
files_ct.data('files', selected).html(files).removeClass('hide');
|
files_ct.data('files', selected).html(files).removeClass('hide');
|
||||||
$('.rm', files_ct).click(function() {
|
$('.rm', files_ct).click(function() {
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
{% load i18n %} {# for file/dir share #}
|
{% load i18n %}
|
||||||
<div id="file-share" class="hide">
|
<div id="file-share" class="hide">
|
||||||
<h3 class="hd">{% trans 'Share %(name)s' %}</h3>
|
<h3 class="hd">{% trans 'Share %(name)s' %}</h3>
|
||||||
<div id="file-share-tabs" class="left-right-tabs ovhd">
|
<div id="file-share-tabs" class="left-right-tabs ovhd">
|
||||||
<ul class="left-right-tabs-nav fleft">
|
<ul class="left-right-tabs-nav fleft">
|
||||||
<li class="tab"><a href="#link-share" class="a">{% trans "Download Link" %}</a></li>
|
<li class="tab"><a href="#link-share" class="a">{% trans "Download Link" %}</a></li>
|
||||||
{% if user_perm == 'rw' %}
|
|
||||||
<li class="tab" id="upload-link-share-tab"><a href="#upload-link-share" class="a">{% trans "Upload Link" %}</a></li>{# for dir #}
|
|
||||||
{% endif %}
|
|
||||||
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}
|
|
||||||
<li class="tab" id="syncable-share-tab"><a href="#syncable-share" class="a">{% trans "Private Share" %}</a></li> {# for dir #}
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="fright">
|
<div class="fright">
|
||||||
@ -58,51 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if user_perm == 'rw' %}
|
|
||||||
<div id="upload-link-share" class="tabs-panel">
|
|
||||||
<p class="tip">{% trans "You can share the generated link to others and then they can upload files to this directory via the link." %}</p>
|
|
||||||
<div id="upload-link-options">
|
|
||||||
<label class="checkbox-label">
|
|
||||||
<span class="checkbox"><input type="checkbox" name="use-passwd" id="upload-link-passwd-switch" class="checkbox-orig" /></span>
|
|
||||||
<span class="checkbox-option">{% trans "Add password protection"%}</span>
|
|
||||||
</label>
|
|
||||||
<div id="upload-link-passwd" class="hide">
|
|
||||||
<label>{% trans "Password"%}</label><span class="tip">{% blocktrans %}(at least {{share_link_password_min_length}} characters){% endblocktrans %}</span><br />
|
|
||||||
<input type="password" name="passwd" disabled="disabled" class="input input-disabled" /><br />
|
|
||||||
<label>{% trans "Password again"%}</label><br />
|
|
||||||
<input type="password" name="passwd_again" disabled="disabled" class="input input-disabled" />
|
|
||||||
</div>
|
|
||||||
<p class="error hide"></p>
|
|
||||||
</div>
|
|
||||||
<button id="gen-upload-link-btn" class="hide">{% trans "Generate"%}</button>
|
|
||||||
<div id="share-upload-link-body" class="hide">
|
|
||||||
<p><span class="vam">{% trans 'Upload Link: ' %}</span><input type="text" readonly="readonly" id="shared-upload-link-text" class="vam" /></p>
|
|
||||||
<button id="send-upload-link">{% trans 'Send' %}</button>
|
|
||||||
<button id="rm-shared-upload-link">{% trans 'Delete' %}</button>
|
|
||||||
|
|
||||||
<form id="upload-link-send-form" action="" method="post" class="hide">{% csrf_token %}
|
|
||||||
<label>{% trans "Send to:"%}</label><br />
|
|
||||||
<input type="text" class="input" id="upload-link-send-input" name="email" placeholder="{% trans "Emails, Seperated by ','"%}" /><br />
|
|
||||||
<input type="hidden" name="shared_upload_link" value="{{ dir_shared_upload_link }}" />
|
|
||||||
<label>{% trans "Message (optional):"%}</label><br />
|
|
||||||
<textarea class="textarea" name="extra_msg" id="upload-extra-msg-text"></textarea><br />
|
|
||||||
<p class="error hide"></p>
|
|
||||||
<input type="submit" value="{% trans "Submit"%}" class="submit" />
|
|
||||||
<input type="button" value="{% trans "Cancel"%}" class="cancel" />
|
|
||||||
<p id="upload-sending" class="hide">{% trans "Sending..."%}</p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}
|
|
||||||
<div id="syncable-share" class="tabs-panel">
|
|
||||||
{% url 'share_repo' as repo_share_url %}
|
|
||||||
{% with post_url=repo_share_url %}
|
|
||||||
{% include "snippets/repo_share_form.html" %} {# for sub-lib share #}
|
|
||||||
{% endwith %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<td><a href="?commit_id={{ dirent.commit_id }}&base={{ dirent.basedir|urlencode }}&p=/{{ dirent.obj_name|urlencode }}&dir_path={{dir_path|urlencode}}">{{ dirent.obj_name }}</a></td>
|
<td><a href="?commit_id={{ dirent.commit_id }}&base={{ dirent.basedir|urlencode }}&p=/{{ dirent.obj_name|urlencode }}&dir_path={{dir_path|urlencode}}">{{ dirent.obj_name }}</a></td>
|
||||||
<td>{{ dirent.delete_time|translate_seahub_time }}</td>
|
<td>{{ dirent.delete_time|translate_seahub_time }}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="op restore-dir hide" href="#" data-url="{% url 'repo_revert_dir' repo.id %}?commit={{ dirent.commit_id }}&p={{ dirent.basedir|urlencode }}{{dirent.obj_name|urlencode}}">{% trans "Restore" %}</a></td>
|
<td><a class="op restore-dir hide" href="#" data-commit_id="{{dirent.commit_id}}" data-path="{{dirent.basedir}}{{dirent.obj_name}}" data-url="{% url 'api2-dir-revert' repo.id %}">{% trans "Restore" %}</a></td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td><a href="?commit_id={{ commit_id }}&base={{ basedir|urlencode }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&dir_path={{dir_path|urlencode}}">{{ dirent.obj_name }}</a></td>
|
<td><a href="?commit_id={{ commit_id }}&base={{ basedir|urlencode }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&dir_path={{dir_path|urlencode}}">{{ dirent.obj_name }}</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
<td><a class="normal" href="{% url 'view_trash_file' repo.id %}?obj_id={{ dirent.obj_id }}&commit_id={{ dirent.commit_id }}&base={{ dirent.basedir|urlencode }}&p=/{{ dirent.obj_name|urlencode }}" target="_blank">{{ dirent.obj_name }}</a></td>
|
<td><a class="normal" href="{% url 'view_trash_file' repo.id %}?obj_id={{ dirent.obj_id }}&commit_id={{ dirent.commit_id }}&base={{ dirent.basedir|urlencode }}&p=/{{ dirent.obj_name|urlencode }}" target="_blank">{{ dirent.obj_name }}</a></td>
|
||||||
<td>{{ dirent.delete_time|translate_seahub_time }}</td>
|
<td>{{ dirent.delete_time|translate_seahub_time }}</td>
|
||||||
<td>{{ dirent.file_size|filesizeformat }}</td>
|
<td>{{ dirent.file_size|filesizeformat }}</td>
|
||||||
<td><a class="op restore-file hide" href="#" data-url="{% url 'repo_revert_file' repo.id %}?commit={{ dirent.commit_id }}&p={{ dirent.basedir|urlencode }}{{dirent.obj_name|urlencode}}">{% trans "Restore" %}</a></td>
|
<td><a class="op restore-file hide" href="#" data-commit_id="{{dirent.commit_id}}" data-path="{{dirent.basedir}}{{dirent.obj_name}}" data-url="{% url 'api2-file-revert' repo.id %}">{% trans "Restore" %}</a></td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td><a class="normal" href="{% url 'view_trash_file' repo.id %}?obj_id={{ dirent.obj_id }}&commit_id={{ commit_id }}&base={{ basedir|urlencode }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}" target="_blank">{{ dirent.obj_name }}</a></td>
|
<td><a class="normal" href="{% url 'view_trash_file' repo.id %}?obj_id={{ dirent.obj_id }}&commit_id={{ commit_id }}&base={{ basedir|urlencode }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}" target="_blank">{{ dirent.obj_name }}</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -33,4 +33,3 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
|
|
||||||
var share_list = [], contacts = [];
|
/*
|
||||||
|
var share_list = [];
|
||||||
$(function () {
|
$(function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url:'{% url 'get_contacts' %}',
|
url:'{% url 'get_contacts' %}',
|
||||||
@ -12,69 +13,21 @@ $(function () {
|
|||||||
for (var i = 0, len = contact_list.length; i < len; i++) {
|
for (var i = 0, len = contact_list.length; i < len; i++) {
|
||||||
contact_email = contact_list[i].email;
|
contact_email = contact_list[i].email;
|
||||||
share_list.push({value: contact_email, label: contact_email});
|
share_list.push({value: contact_email, label: contact_email});
|
||||||
contacts.push({value:contact_email, avatar:contact_list[i].avatar});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
function showSharePopup(op, name, aj_data, type, cur_path) {
|
function showSharePopup(op, name, aj_data, type, cur_path) {
|
||||||
var path;
|
var path = cur_path + name;
|
||||||
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
|
|
||||||
} else {
|
|
||||||
path = cur_path + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
var form = $('#file-share');
|
var form = $('#file-share');
|
||||||
|
form.modal({appendTo: "#main",'focus':false, containerCss:{"padding":0}});
|
||||||
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}
|
|
||||||
var grp_options_ct = $('#share-grp-options');
|
|
||||||
if (!$.trim(grp_options_ct.html())) {
|
|
||||||
var grp_options = '<ul class="option-list">';
|
|
||||||
{% for group in request.user.joined_groups %}
|
|
||||||
grp_options += '<li> <label class="checkbox-label"> <span class="checkbox"><input type="checkbox" name="grp" value="{{ group.group_name }}" class="checkbox-orig"/></span> {{group.avatar|safe}} <span class="checkbox-option">' + "{{ group.group_name }}" + '</span> </label> </li>';
|
|
||||||
{% endfor %}
|
|
||||||
grp_options += '</ul>';
|
|
||||||
grp_options_ct.html(grp_options);
|
|
||||||
}
|
|
||||||
var contact_options_ct = $('#share-contact-options');
|
|
||||||
if (!$.trim(contact_options_ct.html())) {
|
|
||||||
var contact_options = '<ul class="option-list">';
|
|
||||||
for (var i = 0, len = contacts.length; i < len; i++) {
|
|
||||||
contact_email = contacts[i].value;
|
|
||||||
contact_options += ' <li> <label class="checkbox-label"> <span class="checkbox"><input type="checkbox" name="contact" value="' + contact_email + '" class="checkbox-orig" /></span>' + contacts[i].avatar + ' <span class="checkbox-option">' + contact_email + '</span> </label> </li>';
|
|
||||||
}
|
|
||||||
contact_options += '</ul>';
|
|
||||||
contact_options_ct.html(contact_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.checkbox-orig', $('#share-grp-options, #share-contact-options')).click(function() {
|
|
||||||
$(this).parent().toggleClass('checkbox-checked');
|
|
||||||
});
|
|
||||||
$(".checkbox-label", $('#share-grp-options, #share-contact-options')).hover(
|
|
||||||
function() {
|
|
||||||
$(this).addClass('hl');
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
$(this).removeClass('hl');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
form.modal({
|
|
||||||
appendTo: "#main",
|
|
||||||
focus: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var hd = $('#file-share .hd');
|
var hd = $('#file-share .hd');
|
||||||
hd.html(hd.html().replace('%(name)s', '<span class="op-target">' + HTMLescape(trimFilename(name, 30)) + '</span>'));
|
hd.html(hd.html().replace('%(name)s', '<span class="op-target">' + HTMLescape(trimFilename(name, 30)) + '</span>'));
|
||||||
|
|
||||||
if (type == 'd') {
|
|
||||||
$('#private-share-tab, #private-share').remove();
|
|
||||||
} else {
|
|
||||||
$('#syncable-share-tab, #syncable-share, #upload-link-share-tab, #upload-link-share').remove();
|
|
||||||
}
|
|
||||||
$("#file-share-tabs").tabs();
|
$("#file-share-tabs").tabs();
|
||||||
|
|
||||||
// share link
|
// share link
|
||||||
@ -95,61 +48,6 @@ function showSharePopup(op, name, aj_data, type, cur_path) {
|
|||||||
$('input[name="file_shared_name"]').val(name);
|
$('input[name="file_shared_name"]').val(name);
|
||||||
$('input[name="file_shared_type"]').val(type);
|
$('input[name="file_shared_type"]').val(type);
|
||||||
|
|
||||||
{% if user_perm == 'rw' %}
|
|
||||||
// share upload link
|
|
||||||
$('#upload-link-share-tab .a').click(function() {
|
|
||||||
if (op.attr('data-upload-link')) {
|
|
||||||
$('#gen-upload-link-btn, #upload-link-options').addClass('hide');
|
|
||||||
$('#share-upload-link-body').removeClass('hide');
|
|
||||||
var link = op.attr('data-upload-link');
|
|
||||||
$('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(link);
|
|
||||||
$('#main').append('<p id="linkwidth" class="hide">' + link + '</p>');
|
|
||||||
$('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25});
|
|
||||||
$('#linkwidth').remove();
|
|
||||||
} else {
|
|
||||||
$('#gen-upload-link-btn, #upload-link-options').removeClass('hide');
|
|
||||||
$('#share-upload-link-body').addClass('hide');
|
|
||||||
}
|
|
||||||
$('#gen-upload-link-btn').data('aj_data', aj_data).data('obj', op);
|
|
||||||
$('#rm-shared-upload-link').data('obj', op);
|
|
||||||
});
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
// 'private share' for file
|
|
||||||
$('#private-share-tab a').click(function() {
|
|
||||||
var form = $('#private-share-form');
|
|
||||||
$("input[name=s_type]", form).val(type);
|
|
||||||
$("input[name=path]", form).val(path);
|
|
||||||
|
|
||||||
var opts = '', email, avatar;
|
|
||||||
for (var i = 0, len = contacts.length; i < len; i++) {
|
|
||||||
email = contacts[i].value;
|
|
||||||
opts += '<option value="' + email + '" data-index="' + i + '">' + email + '</option>';
|
|
||||||
}
|
|
||||||
var format = function(item) {
|
|
||||||
return contacts[$(item.element).data('index')].avatar + '<span class="vam">' + item.text + '</span>';
|
|
||||||
}
|
|
||||||
$('[name="emails"]', form).html(opts).select2({
|
|
||||||
placeholder: "{% trans "Select contacts" %}",
|
|
||||||
formatResult: format,
|
|
||||||
formatSelection: format,
|
|
||||||
escapeMarkup: function(m) { return m; }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}
|
|
||||||
// syncable share for dir
|
|
||||||
$('#syncable-share-tab a').click(function() {
|
|
||||||
var form = $("#repo-share-form");
|
|
||||||
form.removeClass('hide').css({'width':'auto', 'padding-top':0});
|
|
||||||
$("h3", form).remove();
|
|
||||||
$('.checkbox-label', form).css({'margin-right':'3px'}); // make it not show on top of the scrollbar when hover
|
|
||||||
form.data('dir-path', path);
|
|
||||||
$("#repo-share-tabs").tabs();
|
|
||||||
$('#repo-share-tabs .ui-tabs-nav').css({'padding-left': '1.4em'});
|
|
||||||
});
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
$('#simplemodal-container').css({'height':'auto', 'width':'auto'});
|
$('#simplemodal-container').css({'height':'auto', 'width':'auto'});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +59,7 @@ $('#send-link').click(function() {
|
|||||||
var text = $('#download-extra-msg-text');
|
var text = $('#download-extra-msg-text');
|
||||||
text.css({'width': $('#link-share').width() - parseInt(text.css('padding-left')) - parseInt(text.css('padding-right')) - parseInt(text.css('border-left-width')) - parseInt(text.css('border-right-width'))});
|
text.css({'width': $('#link-share').width() - parseInt(text.css('padding-left')) - parseInt(text.css('padding-right')) - parseInt(text.css('border-left-width')) - parseInt(text.css('border-right-width'))});
|
||||||
$('#link-send-form').removeClass('hide');
|
$('#link-send-form').removeClass('hide');
|
||||||
addAutocomplete('#link-send-input', '#link-send-form', share_list);
|
//addAutocomplete('#link-send-input', '#link-send-form', share_list);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#link-send-form .cancel").click(function() {
|
$("#link-send-form .cancel").click(function() {
|
||||||
@ -241,8 +139,8 @@ $('#gen-link-btn').click(function() {
|
|||||||
obj = gen_link_btn.data('obj'),
|
obj = gen_link_btn.data('obj'),
|
||||||
form = $('#link-options'),
|
form = $('#link-options'),
|
||||||
form_id = form.attr('id'),
|
form_id = form.attr('id'),
|
||||||
use_passwd = $('#link-passwd-switch').attr('checked'),
|
use_passwd = $('#link-passwd-switch').prop('checked'),
|
||||||
set_expiration = $('#link-expire-switch').attr('checked'),
|
set_expiration = $('#link-expire-switch').prop('checked'),
|
||||||
passwd, passwd_again, expire_days, post_data;
|
passwd, passwd_again, expire_days, post_data;
|
||||||
|
|
||||||
if (use_passwd) {
|
if (use_passwd) {
|
||||||
@ -332,193 +230,12 @@ $('#rm-shared-link').click(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
{% if user_perm == 'rw' %}
|
|
||||||
$('#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'))});
|
|
||||||
var text = $('#upload-extra-msg-text');
|
|
||||||
text.css({'width': $('#upload-link-share').width() - parseInt(text.css('padding-left')) - parseInt(text.css('padding-right')) - parseInt(text.css('border-left-width')) - parseInt(text.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('input[name="email"]').val()),
|
|
||||||
submit_btn = form.children('input[type="submit"]'),
|
|
||||||
extra_msg = form.children('textarea[name="extra_msg"]').val();
|
|
||||||
|
|
||||||
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,
|
|
||||||
extra_msg: extra_msg
|
|
||||||
},
|
|
||||||
success: function(data) {
|
|
||||||
$.modal.close();
|
|
||||||
var msg = "{% trans "Successfully sent to {placeholder}" %}"
|
|
||||||
.replace('{placeholder}', data['send_success'].join(', '));
|
|
||||||
feedback(msg, "success");
|
|
||||||
if (data['send_failed'].length > 0) {
|
|
||||||
msg += '<br />' + "{% trans "Failed to send to {placeholder}" %}"
|
|
||||||
.replace('{placeholder}', data['send_failed'].join(', '));
|
|
||||||
feedback(msg, 'info');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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'),
|
|
||||||
form = $('#upload-link-options'),
|
|
||||||
form_id = form.attr('id'),
|
|
||||||
passwd_switch = $('#upload-link-passwd-switch'),
|
|
||||||
use_passwd = passwd_switch.attr('checked'),
|
|
||||||
passwd, passwd_again, post_data;
|
|
||||||
|
|
||||||
if (use_passwd) {
|
|
||||||
passwd = $('input[name="passwd"]', form).val();
|
|
||||||
passwd_again = $('input[name="passwd_again"]', form).val();
|
|
||||||
|
|
||||||
if (!$.trim(passwd)) {
|
|
||||||
apply_form_error(form_id, "{% trans "Please enter password" %}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($.trim(passwd).length < {{share_link_password_min_length}}) {
|
|
||||||
apply_form_error(form_id, "{% trans "Password is too short" %}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!$.trim(passwd_again)) {
|
|
||||||
apply_form_error(form_id, "{% trans "Please enter the password again" %}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($.trim(passwd) != $.trim(passwd_again)) {
|
|
||||||
apply_form_error(form_id, "{% trans "Passwords don't match" %}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
post_data = {'use_passwd': 1, 'passwd': passwd};
|
|
||||||
} else {
|
|
||||||
post_data = {'use_passwd': 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '{% url 'ajax_get_upload_link' %}',
|
|
||||||
type: 'POST',
|
|
||||||
dataType: 'json',
|
|
||||||
beforeSend: prepareCSRFToken,
|
|
||||||
data: $.extend(post_data, {
|
|
||||||
'repo_id': $(this).data('aj_data').repo_id,
|
|
||||||
'p': $(this).data('aj_data').p
|
|
||||||
}),
|
|
||||||
success: function(data) {
|
|
||||||
var upload_link = data['upload_link'];
|
|
||||||
gen_upload_link_btn.addClass('hide');
|
|
||||||
|
|
||||||
$('#upload-link-options, #upload-link-options .error').addClass('hide');
|
|
||||||
$('#upload-link-passwd').hide();
|
|
||||||
$('#upload-link-passwd-switch').attr('checked', false).parent().removeClass('checkbox-checked');
|
|
||||||
$('[type="password"]', form).val('').attr('disabled', false).removeClass('input-disabled');
|
|
||||||
|
|
||||||
$('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(upload_link);
|
|
||||||
$('#main').append('<p id="linkwidth" class="hide">' + upload_link + '</p>');
|
|
||||||
$('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25});
|
|
||||||
$('#linkwidth').remove();
|
|
||||||
$('#share-upload-link-body').removeClass('hide');
|
|
||||||
obj.attr({'data-upload-link': upload_link, 'data-upload-token': data['token']});
|
|
||||||
},
|
|
||||||
error: function(xhr, textStatus, errorThrown) {
|
|
||||||
location.reload(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#rm-shared-upload-link').click(function() {
|
|
||||||
var obj = $(this).data('obj'),
|
|
||||||
token = obj.attr('data-upload-token');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '{% url 'ajax_remove_shared_upload_link' %}',
|
|
||||||
type: 'POST',
|
|
||||||
data: {'t': token},
|
|
||||||
dataType: 'json',
|
|
||||||
cache: false,
|
|
||||||
beforeSend: prepareCSRFToken,
|
|
||||||
success: function(data) {
|
|
||||||
$('#share-upload-link-body').addClass('hide');
|
|
||||||
$('#upload-link-options, #gen-upload-link-btn').removeClass('hide');
|
|
||||||
obj.attr({'data-upload-link': '', 'data-upload-token':''});
|
|
||||||
},
|
|
||||||
error:ajaxErrorHandler
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#upload-link-passwd-switch').click(function () {
|
|
||||||
var form = $('#upload-link-options'),
|
|
||||||
pwd_input = $('input[type="password"]', form);
|
|
||||||
var link_passwd = $('#upload-link-passwd');
|
|
||||||
|
|
||||||
if ($(this).attr('checked')) {
|
|
||||||
pwd_input.attr('disabled', false).removeClass('input-disabled');
|
|
||||||
link_passwd.slideDown(100);
|
|
||||||
} else {
|
|
||||||
link_passwd.slideUp(100);
|
|
||||||
pwd_input.attr('disabled', true).addClass('input-disabled');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
$('#link-passwd-switch').click(function () {
|
$('#link-passwd-switch').click(function () {
|
||||||
var form = $('#link-options'),
|
var form = $('#link-options'),
|
||||||
pwd_input = $('input[type="password"]', form);
|
pwd_input = $('input[type="password"]', form);
|
||||||
var link_passwd = $('#link-passwd');
|
var link_passwd = $('#link-passwd');
|
||||||
|
|
||||||
if ($(this).attr('checked')) {
|
if ($(this).prop('checked')) {
|
||||||
pwd_input.attr('disabled', false).removeClass('input-disabled');
|
pwd_input.attr('disabled', false).removeClass('input-disabled');
|
||||||
link_passwd.slideDown(100);
|
link_passwd.slideDown(100);
|
||||||
} else {
|
} else {
|
||||||
@ -532,7 +249,7 @@ $('#link-expire-switch').click(function () {
|
|||||||
days_input = $('input[name="expire-days"]', form);
|
days_input = $('input[name="expire-days"]', form);
|
||||||
var link_expire = $('#link-expire');
|
var link_expire = $('#link-expire');
|
||||||
|
|
||||||
if ($(this).attr('checked')) {
|
if ($(this).prop('checked')) {
|
||||||
link_expire.slideDown(100);
|
link_expire.slideDown(100);
|
||||||
days_input.attr('disabled', false).removeClass('input-disabled');
|
days_input.attr('disabled', false).removeClass('input-disabled');
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,51 +49,43 @@
|
|||||||
|
|
||||||
{% block extra_script %}
|
{% block extra_script %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var user_list = [], user_email;
|
|
||||||
{% for user in not_admin_users %}
|
|
||||||
user_email = '{{ user.email }}';
|
|
||||||
user_list.push({value:user_email, label:user_email});
|
|
||||||
{% endfor %}
|
|
||||||
$('#add-admin-btn').click(function() {
|
$('#add-admin-btn').click(function() {
|
||||||
var form = $("#add-admin-form");
|
var form = $("#add-admin-form");
|
||||||
form.modal({appendTo: "#main", focus:false});
|
form.modal({appendTo: "#main", focus:false});
|
||||||
$('#simplemodal-container').css({'height':'auto', 'padding':0});
|
$('#simplemodal-container').css({'height':'auto', 'padding':0});
|
||||||
$('#add-admin-tabs').tabs();
|
$('#add-admin-tabs').tabs();
|
||||||
addAutocomplete('#added-member-name', '#enter', user_list);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
$('#add-admin-form').submit(function() {
|
$('#add-admin-form').submit(function() {
|
||||||
var form = $(this),
|
var $form = $(this),
|
||||||
cur_tab_id = $('.ui-tabs-selected a', form).attr('href'),
|
emails = $.trim($('[name="user_email"]', $form).val());
|
||||||
post_data = '',
|
|
||||||
input = $('[name="user_email"]', form);
|
|
||||||
post_data = input.val();
|
|
||||||
|
|
||||||
if (!post_data) {
|
if (!emails) {
|
||||||
apply_form_error(form.attr('id'), '{% trans "Please enter emails, or select some." %}');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var submit_btn = $('[type="submit"]', form);
|
var $submitBtn = $('[type="submit"]', $form);
|
||||||
disable(submit_btn);
|
disable($submitBtn);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '{% url 'batch_user_make_admin' %}',
|
url: '{% url 'batch_user_make_admin' %}',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
cache: false,
|
cache: false,
|
||||||
beforeSend: prepareCSRFToken,
|
beforeSend: prepareCSRFToken,
|
||||||
data: {
|
data: {
|
||||||
'set_admin_emails': post_data
|
'set_admin_emails': emails
|
||||||
},
|
},
|
||||||
success: function(data) {
|
success: function() {
|
||||||
location.reload('true');
|
location.reload(true);
|
||||||
},
|
},
|
||||||
error: function(data, textStatus, jqXHR) {
|
error: function(xhr) {
|
||||||
var errors = $.parseJSON(data.responseText);
|
var error_msg;
|
||||||
$.each(errors, function(index, value) {
|
if (xhr.responseText) {
|
||||||
apply_form_error(form.attr('id'), value);
|
error_msg = $.parseJSON(xhr.responseText).error;
|
||||||
});
|
} else {
|
||||||
enable(submit_btn);
|
error_msg = "{% trans "Failed. Please check the network." %}";
|
||||||
|
}
|
||||||
|
$('.error', $form).html(error_msg).removeClass('hide');
|
||||||
|
enable($submitBtn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
from .settings import *
|
from .settings import *
|
||||||
|
|
||||||
# no cache for testing
|
# no cache for testing
|
||||||
CACHES = {
|
# CACHES = {
|
||||||
'default': {
|
# 'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
# 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
|
|
||||||
# enlarge api throttle
|
# enlarge api throttle
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
@ -15,3 +15,7 @@ REST_FRAMEWORK = {
|
|||||||
'user': '300/minute',
|
'user': '300/minute',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Use static file storage instead of cached, since the cached need to run collect
|
||||||
|
# command first.
|
||||||
|
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import SimpleCookie
|
from django.http import SimpleCookie
|
||||||
@ -161,3 +162,8 @@ class BaseTestCase(TestCase, Fixtures):
|
|||||||
if session_cookie:
|
if session_cookie:
|
||||||
session.delete(session_key=session_cookie.value)
|
session.delete(session_key=session_cookie.value)
|
||||||
self.client.cookies = SimpleCookie()
|
self.client.cookies = SimpleCookie()
|
||||||
|
|
||||||
|
def clear_cache(self):
|
||||||
|
# clear cache between every test case to avoid config option cache
|
||||||
|
# issue which cause test failed
|
||||||
|
cache.clear()
|
||||||
|
63
tests/api/test_dir_revert.py
Normal file
63
tests/api/test_dir_revert.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
from seaserv import seafile_api
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from seahub.test_utils import BaseTestCase
|
||||||
|
|
||||||
|
class DirRevertTest(BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.repo_id = self.repo.id
|
||||||
|
self.folder_path = self.folder
|
||||||
|
self.parent_dir = os.path.dirname(self.folder_path)
|
||||||
|
self.folder_name = os.path.basename(self.folder_path)
|
||||||
|
self.username = self.user.username
|
||||||
|
|
||||||
|
self.url = reverse('api2-dir-revert', args=[self.repo_id])
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.remove_repo()
|
||||||
|
|
||||||
|
def delete_dir(self):
|
||||||
|
seafile_api.del_file(self.repo_id, self.parent_dir,
|
||||||
|
self.folder_name, self.username)
|
||||||
|
|
||||||
|
def get_trash_dir_commit_id(self):
|
||||||
|
deleted_file = seafile_api.get_deleted(self.repo_id, 0, '/', None)
|
||||||
|
|
||||||
|
return deleted_file[0].commit_id
|
||||||
|
|
||||||
|
def get_lib_folder_name(self):
|
||||||
|
|
||||||
|
url = reverse('list_lib_dir', args=[self.repo_id])
|
||||||
|
resp = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||||
|
json_resp = json.loads(resp.content)
|
||||||
|
|
||||||
|
if len(json_resp['dirent_list']) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return json_resp['dirent_list'][0]['obj_name']
|
||||||
|
|
||||||
|
def test_can_revert_dir(self):
|
||||||
|
self.login_as(self.user)
|
||||||
|
|
||||||
|
# check file exist when init
|
||||||
|
assert self.get_lib_folder_name() == self.folder_name
|
||||||
|
|
||||||
|
# delete
|
||||||
|
self.delete_dir()
|
||||||
|
|
||||||
|
# check file not exist after delete
|
||||||
|
assert self.get_lib_folder_name() == None
|
||||||
|
|
||||||
|
# get commit_id of deleted file
|
||||||
|
commit_id = self.get_trash_dir_commit_id()
|
||||||
|
|
||||||
|
resp = self.client.put(self.url,
|
||||||
|
"p=%s&commit_id=%s" % (self.folder_path, commit_id),
|
||||||
|
'application/x-www-form-urlencoded',
|
||||||
|
)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
# check file has been reverted
|
||||||
|
assert self.get_lib_folder_name() == self.folder_name
|
67
tests/api/test_file_revert.py
Normal file
67
tests/api/test_file_revert.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
from seaserv import seafile_api
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from seahub.test_utils import BaseTestCase
|
||||||
|
|
||||||
|
class FileRevertTest(BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.repo_id = self.repo.id
|
||||||
|
self.file_path = self.file
|
||||||
|
self.parent_dir = os.path.dirname(self.file_path)
|
||||||
|
self.file_name = os.path.basename(self.file_path)
|
||||||
|
self.username = self.user.username
|
||||||
|
|
||||||
|
self.url = reverse('api2-file-revert', args=[self.repo_id])
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.remove_repo()
|
||||||
|
|
||||||
|
def delete_file(self):
|
||||||
|
seafile_api.del_file(self.repo_id, self.parent_dir,
|
||||||
|
self.file_name, self.username)
|
||||||
|
|
||||||
|
def get_trash_file_commit_id(self):
|
||||||
|
deleted_file = seafile_api.get_deleted(self.repo_id, 0, '/', None)
|
||||||
|
|
||||||
|
return deleted_file[0].commit_id
|
||||||
|
|
||||||
|
def get_lib_file_name(self):
|
||||||
|
|
||||||
|
url = reverse('list_lib_dir', args=[self.repo_id])
|
||||||
|
resp = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||||
|
json_resp = json.loads(resp.content)
|
||||||
|
|
||||||
|
if len(json_resp['dirent_list']) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return json_resp['dirent_list'][0]['obj_name']
|
||||||
|
|
||||||
|
def test_can_revert_file(self):
|
||||||
|
self.login_as(self.user)
|
||||||
|
|
||||||
|
# check file exist when init
|
||||||
|
assert self.get_lib_file_name() == self.file_name
|
||||||
|
|
||||||
|
# delete
|
||||||
|
self.delete_file()
|
||||||
|
|
||||||
|
# check file not exist after delete
|
||||||
|
assert self.get_lib_file_name() == None
|
||||||
|
|
||||||
|
# get commit_id of deleted file
|
||||||
|
commit_id = self.get_trash_file_commit_id()
|
||||||
|
|
||||||
|
resp = self.client.put(self.url,
|
||||||
|
"p=%s&commit_id=%s" % (self.file_path, commit_id),
|
||||||
|
'application/x-www-form-urlencoded',
|
||||||
|
)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
|
||||||
|
# check file has been reverted
|
||||||
|
assert self.get_lib_file_name() == self.file_name
|
||||||
|
|
||||||
|
def test_can_revert_unicode_filename(self):
|
||||||
|
# todo
|
||||||
|
pass
|
@ -18,6 +18,8 @@ class RepoPublicTest(BaseTestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.remove_repo(self.repo_id)
|
self.remove_repo(self.repo_id)
|
||||||
|
# clear cache between every test case to avoid config option cache issue
|
||||||
|
self.clear_cache()
|
||||||
|
|
||||||
def test_admin_can_set_pub_repo(self):
|
def test_admin_can_set_pub_repo(self):
|
||||||
self.login_as(self.admin)
|
self.login_as(self.admin)
|
||||||
|
@ -16,6 +16,7 @@ class SharedRepoTest(BaseTestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.remove_repo(self.repo_id)
|
self.remove_repo(self.repo_id)
|
||||||
|
self.clear_cache()
|
||||||
|
|
||||||
def test_admin_can_share_repo_to_public(self):
|
def test_admin_can_share_repo_to_public(self):
|
||||||
self.login_as(self.admin)
|
self.login_as(self.admin)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from seahub.test_utils import BaseTestCase
|
from seahub.test_utils import BaseTestCase
|
||||||
from seahub.options.models import (UserOptions, KEY_USER_GUIDE,
|
from seahub.options.models import (UserOptions, KEY_USER_GUIDE,
|
||||||
VAL_USER_GUIDE_ON, VAL_USER_GUIDE_OFF)
|
VAL_USER_GUIDE_ON, VAL_USER_GUIDE_OFF,
|
||||||
|
KEY_DEFAULT_REPO)
|
||||||
|
|
||||||
class UserOptionsManagerTest(BaseTestCase):
|
class UserOptionsManagerTest(BaseTestCase):
|
||||||
def test_is_user_guide_enabled(self):
|
def test_is_user_guide_enabled(self):
|
||||||
@ -25,3 +26,28 @@ class UserOptionsManagerTest(BaseTestCase):
|
|||||||
assert UserOptions.objects.is_user_guide_enabled(self.user.email) is True
|
assert UserOptions.objects.is_user_guide_enabled(self.user.email) is True
|
||||||
assert len(UserOptions.objects.filter(email=self.user.email,
|
assert len(UserOptions.objects.filter(email=self.user.email,
|
||||||
option_key=KEY_USER_GUIDE)) == 1
|
option_key=KEY_USER_GUIDE)) == 1
|
||||||
|
|
||||||
|
def test_get_default_repo(self):
|
||||||
|
assert len(UserOptions.objects.filter(email=self.user.email, option_key=KEY_DEFAULT_REPO)) == 0
|
||||||
|
|
||||||
|
UserOptions.objects.create(email=self.user.email,
|
||||||
|
option_key=KEY_DEFAULT_REPO,
|
||||||
|
option_val=self.repo.id)
|
||||||
|
|
||||||
|
assert len(UserOptions.objects.filter(email=self.user.email, option_key=KEY_DEFAULT_REPO)) == 1
|
||||||
|
assert UserOptions.objects.get_default_repo(self.user.email) is not None
|
||||||
|
|
||||||
|
def test_get_default_repo_with_multiple_records(self):
|
||||||
|
assert len(UserOptions.objects.filter(email=self.user.email, option_key=KEY_DEFAULT_REPO)) == 0
|
||||||
|
|
||||||
|
UserOptions.objects.create(email=self.user.email,
|
||||||
|
option_key=KEY_DEFAULT_REPO,
|
||||||
|
option_val=self.repo.id)
|
||||||
|
|
||||||
|
UserOptions.objects.create(email=self.user.email,
|
||||||
|
option_key=KEY_DEFAULT_REPO,
|
||||||
|
option_val=self.repo.id)
|
||||||
|
|
||||||
|
assert len(UserOptions.objects.filter(email=self.user.email, option_key=KEY_DEFAULT_REPO)) == 2
|
||||||
|
assert UserOptions.objects.get_default_repo(self.user.email) is not None
|
||||||
|
assert len(UserOptions.objects.filter(email=self.user.email, option_key=KEY_DEFAULT_REPO)) == 1
|
||||||
|
35
tests/seahub/profile/models/test_update_nickname_cache.py
Normal file
35
tests/seahub/profile/models/test_update_nickname_cache.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||||
|
from seahub.profile.models import Profile
|
||||||
|
from seahub.test_utils import BaseTestCase
|
||||||
|
|
||||||
|
from tests.common.utils import randstring
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateNicknameCacheTest(BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.tmp_user = self.create_user('user_%s@test.com' % randstring(4),
|
||||||
|
is_staff=False)
|
||||||
|
assert len(Profile.objects.all()) == 0
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.remove_user(self.tmp_user.username)
|
||||||
|
|
||||||
|
def test_update_when_call_object_method(self):
|
||||||
|
username = self.tmp_user.username
|
||||||
|
assert email2nickname(username) == username.split('@')[0]
|
||||||
|
|
||||||
|
Profile.objects.add_or_update(username, 'nickname')
|
||||||
|
assert email2nickname(username) == 'nickname'
|
||||||
|
|
||||||
|
def test_updated_when_call_save(self):
|
||||||
|
username = self.tmp_user.username
|
||||||
|
assert email2nickname(username) == username.split('@')[0]
|
||||||
|
|
||||||
|
p = Profile.objects.get_profile_by_user(username)
|
||||||
|
if p is None:
|
||||||
|
p = Profile(user=username)
|
||||||
|
|
||||||
|
p.nickname = 'nickname'
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
assert email2nickname(username) == 'nickname'
|
33
tests/seahub/profile/views/test_edit_profile.py
Normal file
33
tests/seahub/profile/views/test_edit_profile.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
|
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||||
|
from seahub.profile.models import Profile
|
||||||
|
from seahub.test_utils import BaseTestCase
|
||||||
|
from tests.common.utils import randstring
|
||||||
|
|
||||||
|
class EditProfileTest(BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.tmp_user = self.create_user('user_%s@test.com' % randstring(4),
|
||||||
|
is_staff=False)
|
||||||
|
assert len(Profile.objects.all()) == 0
|
||||||
|
|
||||||
|
self.url = reverse('edit_profile')
|
||||||
|
self.login_as(self.tmp_user)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.remove_user(self.tmp_user.username)
|
||||||
|
|
||||||
|
def test_can_render_edit_page(self):
|
||||||
|
resp = self.client.get(self.url)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.assertTemplateUsed(resp, 'profile/set_profile.html')
|
||||||
|
|
||||||
|
def test_can_edit(self):
|
||||||
|
assert email2nickname(self.tmp_user.username) == self.tmp_user.username.split('@')[0]
|
||||||
|
|
||||||
|
resp = self.client.post(self.url, {
|
||||||
|
'nickname': 'new nickname'
|
||||||
|
})
|
||||||
|
self.assertEqual(302, resp.status_code)
|
||||||
|
self.assertRegexpMatches(resp['Location'], r'http://testserver/profile/')
|
||||||
|
assert email2nickname(self.tmp_user.username) == 'new nickname'
|
@ -27,6 +27,8 @@ class LibrariesTest(BaseTestCase):
|
|||||||
assert UserOptions.objects.is_user_guide_enabled(username) is False
|
assert UserOptions.objects.is_user_guide_enabled(username) is False
|
||||||
|
|
||||||
def test_pub_repo_creation_config(self):
|
def test_pub_repo_creation_config(self):
|
||||||
|
self.clear_cache()
|
||||||
|
|
||||||
# user
|
# user
|
||||||
self.login_as(self.user)
|
self.login_as(self.user)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user