mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 07:01:12 +00:00
add new api & update code
1. add new repo set password api 2. update repo url related code
This commit is contained in:
48
seahub/api2/endpoints/repo_set_password.py
Normal file
48
seahub/api2/endpoints/repo_set_password.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from seaserv import seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.utils import api_error
|
||||
|
||||
class RepoSetPassword(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication )
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def post(self, request, repo_id):
|
||||
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
password = request.POST.get('password', None)
|
||||
if not password:
|
||||
error_msg = 'password invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
try:
|
||||
seafile_api.set_passwd(repo_id, request.user.username, password)
|
||||
return Response({'success': True})
|
||||
except SearpcError as e:
|
||||
if e.msg == 'Bad arguments':
|
||||
error_msg = 'Bad arguments'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
elif e.msg == 'Incorrect password':
|
||||
error_msg = _(u'Wrong password')
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
elif e.msg == 'Internal server error':
|
||||
error_msg = _(u'Internal server error')
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
else:
|
||||
error_msg = _(u'Decrypt library error')
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
@@ -128,31 +128,6 @@ class RepoNewDirentForm(forms.Form):
|
||||
except SearpcError, e:
|
||||
raise forms.ValidationError(str(e))
|
||||
|
||||
class RepoPassowrdForm(forms.Form):
|
||||
"""
|
||||
Form for user to decrypt a repo in repo page.
|
||||
"""
|
||||
repo_id = forms.CharField(error_messages={'required': _('Repo id is required')})
|
||||
username = forms.CharField(error_messages={'required': _('Username is required')})
|
||||
password = forms.CharField(error_messages={'required': _('Password can\'t be empty')})
|
||||
|
||||
def clean(self):
|
||||
if 'password' in self.cleaned_data:
|
||||
repo_id = self.cleaned_data['repo_id']
|
||||
username = self.cleaned_data['username']
|
||||
password = self.cleaned_data['password']
|
||||
try:
|
||||
seafserv_threaded_rpc.set_passwd(repo_id, username, password)
|
||||
except SearpcError, e:
|
||||
if e.msg == 'Bad arguments':
|
||||
raise forms.ValidationError(_(u'Bad url format'))
|
||||
elif e.msg == 'Incorrect password':
|
||||
raise forms.ValidationError(_(u'Wrong password'))
|
||||
elif e.msg == 'Internal server error':
|
||||
raise forms.ValidationError(_(u'Internal server error'))
|
||||
else:
|
||||
raise forms.ValidationError(_(u'Decrypt library error'))
|
||||
|
||||
class SetUserQuotaForm(forms.Form):
|
||||
"""
|
||||
Form for setting user quota.
|
||||
|
@@ -66,7 +66,7 @@
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="{% trans "Directory icon"%}" height="20" class="vam" />
|
||||
<a href="{% url 'repo' ma.repo_id %}?p={{ ma.path|urlencode }}" target="_blank" class="vam">{{ ma.name }}</a>
|
||||
<a href="{% url 'view_common_lib_dir' ma.repo_id ma.path|urlencode|strip_slash %}" target="_blank" class="vam">{{ ma.name }}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
<a href="{% url 'view_lib_file' ma.repo_id ma.path|urlencode %}" target="_blank" class="vam">{{ ma.name }}</a>
|
||||
{% else %}
|
||||
<img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="{% trans "Directory icon"%}" height="20" class="vam" />
|
||||
<a href="{% url 'repo' ma.repo_id %}?p={{ ma.path|urlencode }}" target="_blank" class="vam">{{ ma.name }}</a>
|
||||
<a href="{% url 'view_common_lib_dir' ma.repo_id ma.path|urlencode|strip_slash %}" target="_blank" class="vam">{{ ma.name }}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
@@ -124,7 +124,7 @@ class Command(BaseCommand):
|
||||
if repo is None:
|
||||
notice.delete()
|
||||
|
||||
notice.repo_url = reverse("view_common_lib_dir", args=[repo_id, '/'])
|
||||
notice.repo_url = reverse("view_common_lib_dir", args=[repo_id, ''])
|
||||
notice.notice_from = escape(email2nickname(d['share_from']))
|
||||
notice.repo_name = repo.name
|
||||
notice.avatar_src = self.get_avatar_src(d['share_from'])
|
||||
|
@@ -5,10 +5,8 @@
|
||||
<div class="wide-panel">
|
||||
<h2>{{repo.name}}</h2>
|
||||
<p class="access-notice">{% trans "This library is encrypted. Please input the password if you want to browse it online. And the password will be kept on the server for only 1 hour." %}</p>
|
||||
<form action="{% url 'repo' repo.id %}?next={{ next }}" method="post" id="repo-decrypt-form">{% csrf_token %}
|
||||
<form action="" method="post" id="repo-decrypt-form">{% csrf_token %}
|
||||
<label>{% trans "Password: " %}</label>
|
||||
<input type="hidden" name="repo_id" value="{{ repo.id }}" />
|
||||
<input type="hidden" name="username" value="{{ request.user.username }}" />
|
||||
<input type="password" name="password" autofocus />
|
||||
<input type="submit" value="{% trans "Submit" %}" />
|
||||
<p class="error hide"></p>
|
||||
@@ -27,12 +25,35 @@
|
||||
<script type="text/javascript">
|
||||
$('#repo-decrypt-form').submit(function() {
|
||||
var form = $(this),
|
||||
pwd = $('[name="password"]', form).val(),
|
||||
err = $('.error',form);
|
||||
if (!$.trim(pwd)) {
|
||||
form_id = $(this).attr('id');
|
||||
password = $('[name="password"]', form).val(),
|
||||
err = $('.error',form),
|
||||
repo_id = "{{ repo.id }}",
|
||||
username = "{{ request.user.username }}",
|
||||
redirect_url = "{{ next }}";
|
||||
|
||||
if (!$.trim(password)) {
|
||||
err.html("{% trans "Please enter the password." %}").removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "{% url 'api-v2.1-repo-set-password' repo.id %}",
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {password: password},
|
||||
success: function(data) {
|
||||
location.href = redirect_url;
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
var error_msg = $.parseJSON(jqXHR.responseText).error_msg;
|
||||
apply_form_error(form_id, error_msg);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -412,15 +412,13 @@ $('#repo-decrypt-form').submit(function() {
|
||||
err.html("{% trans "Password is required." %}");
|
||||
} else {
|
||||
$.ajax({
|
||||
url: '{% url 'repo_set_password' %}',
|
||||
url: '{% url 'api-v2.1-repo-set-password' repo.id %}',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
cache: 'false',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {
|
||||
repo_id: '{{repo.id}}',
|
||||
password: pwd,
|
||||
username: '{{request.user.username}}'
|
||||
password: pwd
|
||||
},
|
||||
success: function(data) {
|
||||
if (data['success']) {
|
||||
@@ -436,7 +434,7 @@ $('#repo-decrypt-form').submit(function() {
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
var err_str = '';
|
||||
if (jqXHR.responseText) {
|
||||
err_str = $.parseJSON(jqXHR.responseText).error;
|
||||
err_str = $.parseJSON(jqXHR.responseText).error_msg;
|
||||
} else {
|
||||
err_str = "{% trans "Failed. Please check the network." %}";
|
||||
}
|
||||
|
@@ -1,43 +0,0 @@
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
$('#repo-decrypt-form').submit(function() {
|
||||
var form = $(this);
|
||||
var form_id = form.attr('id');
|
||||
var input_password = form.find('input[name="password"]');
|
||||
var repo_id = form.find('input[name="repo_id"]').val();
|
||||
var password = input_password.val();
|
||||
var cur_data = form.data();
|
||||
if (!password) {
|
||||
apply_form_error(form_id, "{% trans "Password is required." %}");
|
||||
} else {
|
||||
apply_form_error(form_id, '');
|
||||
$.ajax({
|
||||
url: '{% url 'repo_set_password' %}',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
cache: 'false',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {
|
||||
repo_id: repo_id,
|
||||
password: password,
|
||||
username: '{{request.user.username}}'
|
||||
},
|
||||
success: function(data) {
|
||||
$.modal.close();
|
||||
$('.lsch-encrypted[data-repoid="' + repo_id + '"]').attr('data-passwordset', true);
|
||||
listCommitDetails(cur_data.url, cur_data.time);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
var err = '';
|
||||
if (jqXHR.responseText) {
|
||||
err = $.parseJSON(jqXHR.responseText).error;
|
||||
} else {
|
||||
err = "{% trans "Failed. Please check the network." %}";
|
||||
}
|
||||
apply_form_error(form_id, err);
|
||||
input_password.val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
@@ -25,6 +25,7 @@ from seahub.api2.endpoints.share_links import ShareLinks, ShareLink
|
||||
from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink
|
||||
from seahub.api2.endpoints.file import FileView
|
||||
from seahub.api2.endpoints.dir import DirView
|
||||
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
#from django.contrib import admin
|
||||
@@ -66,7 +67,6 @@ urlpatterns = patterns(
|
||||
|
||||
(r'^repo/upload_check/$', validate_filename),
|
||||
url(r'^repo/unsetinnerpub/(?P<repo_id>[-0-9a-f]{36})/$', unsetinnerpub, name='unsetinnerpub'),
|
||||
url(r'^repo/set_password/$', repo_set_password, name="repo_set_password"),
|
||||
url(r'^repo/download_dir/(?P<repo_id>[-0-9a-f]{36})/$', repo_download_dir, name='repo_download_dir'),
|
||||
(r'^repo/upload_error/(?P<repo_id>[-0-9a-f]{36})/$', upload_file_error),
|
||||
(r'^repo/update_error/(?P<repo_id>[-0-9a-f]{36})/$', update_file_error),
|
||||
@@ -189,6 +189,7 @@ urlpatterns = patterns(
|
||||
url(r'^api/v2.1/upload-link/(?P<token>[a-f0-9]{10})/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
||||
|
||||
(r'^avatar/', include('seahub.avatar.urls')),
|
||||
(r'^notification/', include('seahub.notifications.urls')),
|
||||
|
@@ -42,7 +42,6 @@ from seahub.options.models import UserOptions, CryptoOptionNotSetError
|
||||
from seahub.profile.models import Profile
|
||||
from seahub.share.models import FileShare, PrivateFileDirShare, \
|
||||
UploadLinkShare
|
||||
from seahub.forms import RepoPassowrdForm
|
||||
from seahub.utils import render_permission_error, render_error, list_to_string, \
|
||||
get_fileserver_root, gen_shared_upload_link, is_org_context, \
|
||||
gen_dir_share_link, gen_file_share_link, get_repo_last_modify, \
|
||||
@@ -215,7 +214,7 @@ def get_repo_dirents(request, repo, commit, path, offset=-1, limit=-1):
|
||||
uploadlinks = UploadLinkShare.objects.filter(repo_id=repo.id).filter(username=username)
|
||||
|
||||
|
||||
view_dir_base = reverse("view_common_lib_dir", args=[repo.id, '/'])
|
||||
view_dir_base = reverse("view_common_lib_dir", args=[repo.id, ''])
|
||||
dl_dir_base = reverse('repo_download_dir', args=[repo.id])
|
||||
file_history_base = reverse('file_revisions', args=[repo.id])
|
||||
for dirent in dirs:
|
||||
@@ -652,7 +651,7 @@ def repo_history(request, repo_id):
|
||||
return render_error(request, e.msg)
|
||||
|
||||
if not password_set:
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '/']))
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '']))
|
||||
|
||||
try:
|
||||
current_page = int(request.GET.get('page', '1'))
|
||||
@@ -722,7 +721,7 @@ def repo_revert_history(request, repo_id):
|
||||
return render_error(request, e.msg)
|
||||
|
||||
if not password_set:
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '/']))
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '']))
|
||||
|
||||
commit_id = request.GET.get('commit_id', '')
|
||||
if not commit_id:
|
||||
@@ -964,7 +963,7 @@ def repo_set_access_property(request, repo_id):
|
||||
ap = request.GET.get('ap', '')
|
||||
seafserv_threaded_rpc.repo_set_access_property(repo_id, ap)
|
||||
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '/']))
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '']))
|
||||
|
||||
@login_required
|
||||
def file_upload_progress_page(request):
|
||||
@@ -1111,7 +1110,7 @@ def repo_revert_file(request, repo_id):
|
||||
return HttpResponseRedirect(next)
|
||||
|
||||
if ret == 1:
|
||||
root_url = reverse('view_common_lib_dir', args=[repo_id, '/'])
|
||||
root_url = reverse('view_common_lib_dir', args=[repo_id, ''])
|
||||
msg = _(u'Successfully revert %(path)s to <a href="%(root)s">root directory.</a>') % {"path": escape(path.lstrip('/')), "root": root_url}
|
||||
messages.success(request, msg, extra_tags='safe')
|
||||
else:
|
||||
@@ -1150,7 +1149,7 @@ def repo_revert_dir(request, repo_id):
|
||||
return HttpResponseRedirect(next)
|
||||
|
||||
if ret == 1:
|
||||
root_url = reverse('view_common_lib_dir', args=[repo_id, '/'])
|
||||
root_url = reverse('view_common_lib_dir', args=[repo_id, ''])
|
||||
msg = _(u'Successfully revert %(path)s to <a href="%(url)s">root directory.</a>') % {"path": escape(path.lstrip('/')), "url": root_url}
|
||||
messages.success(request, msg, extra_tags='safe')
|
||||
else:
|
||||
@@ -1200,17 +1199,6 @@ def list_inner_pub_repos(request):
|
||||
|
||||
return []
|
||||
|
||||
@login_required_ajax
|
||||
def repo_set_password(request):
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
form = RepoPassowrdForm(request.POST)
|
||||
if form.is_valid():
|
||||
return HttpResponse(json.dumps({'success': True}), content_type=content_type)
|
||||
else:
|
||||
return HttpResponse(json.dumps({'error': str(form.errors.values()[0])}),
|
||||
status=400, content_type=content_type)
|
||||
|
||||
def i18n(request):
|
||||
"""
|
||||
Set client language preference, lasts for one month
|
||||
|
@@ -144,13 +144,13 @@ def repo_history_view(request, repo_id):
|
||||
and not is_password_set(repo.id, username):
|
||||
return render_to_response('decrypt_repo_form.html', {
|
||||
'repo': repo,
|
||||
'next': get_next_url_from_request(request) or reverse("view_common_lib_dir", args=[repo_id, '/']),
|
||||
'next': get_next_url_from_request(request) or reverse("view_common_lib_dir", args=[repo_id, '']),
|
||||
'force_server_crypto': FORCE_SERVER_CRYPTO,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
commit_id = request.GET.get('commit_id', None)
|
||||
if commit_id is None:
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '/']))
|
||||
return HttpResponseRedirect(reverse("view_common_lib_dir", args=[repo_id, '']))
|
||||
current_commit = get_commit(repo.id, repo.version, commit_id)
|
||||
if not current_commit:
|
||||
current_commit = get_commit(repo.id, repo.version, repo.head_cmmt_id)
|
||||
|
@@ -299,11 +299,9 @@ define([
|
||||
Common.ajaxPost({
|
||||
form: form,
|
||||
form_id: form.attr('id'),
|
||||
post_url: Common.getUrl({'name':'repo_set_password'}),
|
||||
post_url: Common.getUrl({'name':'api_v2.1_repo_set_password', repo_id: _this.dir.repo_id}),
|
||||
post_data: {
|
||||
repo_id: _this.dir.repo_id,
|
||||
password: passwd,
|
||||
username: app.pageOptions.username
|
||||
password: passwd
|
||||
},
|
||||
after_op_success: function() {
|
||||
decrypt_success = true;
|
||||
|
@@ -97,7 +97,7 @@ define([
|
||||
case 'sub_repo': return siteRoot + 'ajax/repo/' + options.repo_id + '/dir/sub_repo/';
|
||||
case 'get_my_unenc_repos': return siteRoot + 'ajax/my-unenc-repos/';
|
||||
case 'unenc_rw_repos': return siteRoot + 'ajax/unenc-rw-repos/';
|
||||
case 'repo_set_password': return siteRoot + 'repo/set_password/';
|
||||
case 'api_v2.1_repo_set_password': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/set-password/';
|
||||
case 'get_folder_perm_by_path': return siteRoot + 'ajax/repo/' + options.repo_id + '/get-folder-perm-by-path/';
|
||||
case 'get_history_changes': return siteRoot + 'ajax/repo/' + options.repo_id + '/history/changes/';
|
||||
case 'ajax_repo_remove_share': return siteRoot + 'share/ajax/repo_remove_share/';
|
||||
@@ -386,7 +386,7 @@ define([
|
||||
after_op_error = function(xhr, textStatus, errorThrown) {
|
||||
var err;
|
||||
if (xhr.responseText) {
|
||||
err = $.parseJSON(xhr.responseText).error;
|
||||
err = $.parseJSON(xhr.responseText).error||$.parseJSON(xhr.responseText).error_msg;
|
||||
} else {
|
||||
err = gettext("Failed. Please check the network.");
|
||||
}
|
||||
|
35
tests/api/endpoints/test_repo_set_password.py
Normal file
35
tests/api/endpoints/test_repo_set_password.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#coding: UTF-8
|
||||
import json
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from seaserv import seafile_api
|
||||
from seahub.test_utils import BaseTestCase
|
||||
from tests.common.utils import randstring
|
||||
|
||||
|
||||
class RepoSetPasswordTest(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
self.password = randstring(6)
|
||||
self.repo_id = seafile_api.create_repo('test-repo',
|
||||
'', self.user.username, self.password)
|
||||
|
||||
def tearDown(self):
|
||||
self.remove_repo(self.repo_id)
|
||||
|
||||
def test_decrypt_repo(self):
|
||||
url = reverse("api-v2.1-repo-set-password", args=[self.repo_id])
|
||||
data = {"password": self.password,}
|
||||
resp = self.client.post(url, data)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_can_not_decrypt_repo_with_wrong_password(self):
|
||||
url = reverse("api-v2.1-repo-set-password", args=[self.repo_id])
|
||||
data = {"password": 'invalid-password',}
|
||||
|
||||
resp = self.client.post(url, data)
|
||||
self.assertEqual(403, resp.status_code)
|
||||
json_resp = json.loads(resp.content)
|
||||
assert json_resp['error_msg'] == 'Wrong password'
|
Reference in New Issue
Block a user