1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 15:09:14 +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:
lian
2016-03-21 15:38:22 +08:00
parent 0d57b3f060
commit 69cbd56064
14 changed files with 144 additions and 123 deletions

View 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)

View File

@@ -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.

View File

@@ -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 %}

View File

@@ -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 %}

View File

@@ -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'])

View File

@@ -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 %}

View File

@@ -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." %}";
}

View File

@@ -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;
});

View File

@@ -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')),

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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.");
}

View 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'