1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-04 16:31:13 +00:00

use djangorestframwork in api

This commit is contained in:
poet
2012-07-14 20:26:41 +08:00
parent f29db5b649
commit f441158f9e
4 changed files with 210 additions and 141 deletions

View File

@@ -4,12 +4,14 @@ from views import *
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^/$', list_repo), url(r'^$', ReposView.as_view()),
url(r'^repo/list/$', list_repo), url(r'^/$', ReposView.as_view()),
url(r'^repo/(?P<repo_id>[^/]+)/$', get_repo_info), url(r'^repo/list/$', ReposView.as_view(), name='repos'),
url(r'^dir/(?P<repo_id>[^/]+)/root/$', get_repo_dir_path), url(r'^repo/(?P<repo_id>[^/]+)/$', RepoView.as_view(), name='repo'),
url(r'^dir/(?P<repo_id>[^/]+)/$', get_repo_dir_path),
url(r'^dir/(?P<repo_id>[^/]+)/(?P<dir_id>[^/]+)/$', get_repo_dir_id), url(r'^dir/(?P<repo_id>[^/]+)/root/$', RepoDirPathView.as_view()),
url(r'^file/(?P<repo_id>[^/]+)/(?P<file_id>[^/]+)/$', get_repo_file_id), url(r'^dir/(?P<repo_id>[^/]+)/$', RepoDirPathView.as_view(), name='repo-dir-path'),
url(r'^dir/(?P<repo_id>[^/]+)/(?P<dir_id>[^/]+)/$', RepoDirIdView.as_view(), name='repo-dirr-id'),
url(r'^file/(?P<repo_id>[^/]+)/(?P<file_id>[^/]+)/$', RepoFileView.as_view(), name='repo-file'),
) )

View File

@@ -6,7 +6,7 @@ import stat
import simplejson as json import simplejson as json
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError
from auth.decorators import login_required from auth.decorators import login_required, api_login_required
from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_groups, get_users, get_repos, \ from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_groups, get_users, get_repos, \
get_repo, get_commits, get_branches, \ get_repo, get_commits, get_branches, \
@@ -19,6 +19,15 @@ from seahub.utils import list_to_string, \
check_filename_with_rename, get_accessible_repos, EMPTY_SHA1 check_filename_with_rename, get_accessible_repos, EMPTY_SHA1
from seahub.views import access_to_repo, validate_owner from seahub.views import access_to_repo, validate_owner
from pysearpc import SearpcError
from djangorestframework.renderers import JSONRenderer
from djangorestframework.compat import View
from djangorestframework.mixins import ResponseMixin
from djangorestframework.response import Response
from django.core.urlresolvers import reverse
json_content_type = 'application/json; charset=utf-8' json_content_type = 'application/json; charset=utf-8'
@@ -26,7 +35,7 @@ json_content_type = 'application/json; charset=utf-8'
def api_error(request, code='404', msg=None): def api_error(request, code='404', msg=None):
err_resp = {'error_msg':msg} err_resp = {'error_msg':msg}
return HttpResponse(json.dumps(err_resp), status=code, return HttpResponse(json.dumps(err_resp), status=code,
content_type=json_content_type) content_type=json_content_type)
def can_access_repo(request, repo_id): def can_access_repo(request, repo_id):
repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id) repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id)
@@ -36,6 +45,7 @@ def can_access_repo(request, repo_id):
# check whether user can view repo # check whether user can view repo
return access_to_repo(request, repo_id, repo_ap) return access_to_repo(request, repo_id, repo_ap)
def get_dir_entrys_by_path(reqquest, commit, path): def get_dir_entrys_by_path(reqquest, commit, path):
dentrys = [] dentrys = []
if path[-1] != '/': if path[-1] != '/':
@@ -43,8 +53,8 @@ def get_dir_entrys_by_path(reqquest, commit, path):
if not commit.root_id == EMPTY_SHA1: if not commit.root_id == EMPTY_SHA1:
try: try:
dirs = seafserv_rpc.list_dir_by_path(commit.id, dirs = seafserv_threaded_rpc.list_dir_by_path(commit.id,
path.encode('utf-8')) path.encode('utf-8'))
except SearpcError, e: except SearpcError, e:
return api_error(request, "404", e.msg) return api_error(request, "404", e.msg)
for dirent in dirs: for dirent in dirs:
@@ -67,7 +77,7 @@ def get_dir_entrys_by_path(reqquest, commit, path):
def get_dir_entrys_by_id(reqquest, dir_id): def get_dir_entrys_by_id(reqquest, dir_id):
dentrys = [] dentrys = []
try: try:
dirs = seafserv_rpc.list_dir(dir_id) dirs = seafserv_threaded_rpc.list_dir(dir_id)
except SearpcError, e: except SearpcError, e:
return api_error(request, "404", e.msg) return api_error(request, "404", e.msg)
for dirent in dirs: for dirent in dirs:
@@ -87,79 +97,85 @@ def get_dir_entrys_by_id(reqquest, dir_id):
return HttpResponse(json.dumps(dentrys), status=200, return HttpResponse(json.dumps(dentrys), status=200,
content_type=json_content_type) content_type=json_content_type)
@login_required class ReposView(ResponseMixin, View):
def list_repo(request): renderers = (JSONRenderer,)
email = request.user.username
owned_repos = seafserv_threaded_rpc.list_owned_repos(email) @api_login_required
calculate_repo_last_modify(owned_repos) def get(self, request):
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify)) email = request.user.username
n_repos = seafserv_threaded_rpc.list_share_repos(email, owned_repos = seafserv_threaded_rpc.list_owned_repos(email)
'to_email', -1, -1) calculate_repo_last_modify(owned_repos)
calculate_repo_last_modify(owned_repos) owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
repos_json = [] n_repos = seafserv_threaded_rpc.list_share_repos(email,
for r in owned_repos: 'to_email', -1, -1)
repo = { calculate_repo_last_modify(owned_repos)
"id":r.props.id, owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
"owner":"self",
"name":r.props.name,
"desc":r.props.desc,
"mtime":r.lastest_modify,
}
repos_json.append(repo)
for r in n_repos: repos_json = []
repo = { for r in owned_repos:
"id":r.props.id, repo = {
"owner":r.props.shared_email, "id":r.props.id,
"name":r.props.name, "owner":"self",
"desc":r.props.desc, "name":r.props.name,
"mtime":r.lastest_modify, "desc":r.props.desc,
} "mtime":r.lastest_modify,
repos_json.append(repo) }
return HttpResponse(json.dumps(repos_json), status=200, repos_json.append(repo)
content_type=json_content_type)
for r in n_repos:
repo = {
"id":r.props.id,
"owner":r.props.shared_email,
"name":r.props.name,
"desc":r.props.desc,
"mtime":r.lastest_modify,
}
repos_json.append(repo)
@login_required response = Response(200, repos_json)
def get_repo_info(request, repo_id): return self.render(response)
# check whether user can view repo
if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
# check whether use is repo owner class RepoView(ResponseMixin, View):
if validate_owner(request, repo_id): renderers = (JSONRenderer,)
owner = "self"
else:
owner = "share"
repo = get_repo(repo_id)
if not repo:
return api_error(request, '404', "repo not found")
try: @api_login_required
repo.latest_modify = get_commits(repo.id, 0, 1)[0].ctime def get_repo_info(request, repo_id):
except: # check whether user can view repo
repo.latest_modify = None if not can_access_repo(request, repo_id):
# query whether set password if repo is encrypted return api_error(request, '403', "can not access repo")
# check whether use is repo owner
if validate_owner(request, repo_id):
owner = "self"
else:
owner = "share"
repo = get_repo(repo_id)
if not repo:
return api_error(request, '404', "repo not found")
password_set = False
if repo.props.encrypted:
try: try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username) repo.latest_modify = get_commits(repo.id, 0, 1)[0].ctime
if ret == 1: except:
password_set = True repo.latest_modify = None
except SearpcError, e:
return api_error(request, '403', e.msg)
# query repo infomation # query whether set password if repo is encrypted
repo_size = seafserv_threaded_rpc.server_repo_size(repo_id) password_set = False
current_commit = get_commits(repo_id, 0, 1)[0] if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
repo_json = { # query repo infomation
repo_size = seafserv_threaded_rpc.server_repo_size(repo_id)
current_commit = get_commits(repo_id, 0, 1)[0]
repo_json = {
"id":repo.props.id, "id":repo.props.id,
"owner":owner, "owner":owner,
"name":repo.props.name, "name":repo.props.name,
@@ -169,90 +185,104 @@ def get_repo_info(request, repo_id):
"size":repo_size, "size":repo_size,
"commit":current_commit.id, "commit":current_commit.id,
} }
return HttpResponse(json.dumps(repo_json), status=200, response = Response(200, repo_json)
content_type=json_content_type) return self.render(response)
@login_required class RepoDirPathView(ResponseMixin, View):
def get_repo_dir_path(request, repo_id): renderers = (JSONRenderer,)
if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
current_commit = get_commits(repo_id, 0, 1)[0]
repo = get_repo(repo_id) @api_login_required
if not repo: def get(self, request, repo_id):
return api_error(request, '404', "repo not found") if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
current_commit = get_commits(repo_id, 0, 1)[0]
password_set = False repo = get_repo(repo_id)
if repo.props.encrypted: if not repo:
try: return api_error(request, '404', "repo not found")
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
if repo.props.encrypted and not password_set:
return api_error(request, '403', "password needed")
path = request.GET.get('p', '/') password_set = False
return get_dir_entrys_by_path(request, current_commit, path) if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
if repo.props.encrypted and not password_set:
return api_error(request, '403', "password needed")
path = request.GET.get('p', '/')
return get_dir_entrys_by_path(request, current_commit, path)
@login_required
def get_repo_dir_id(request, repo_id, dir_id):
if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
repo = get_repo(repo_id) class RepoDirIdView(ResponseMixin, View):
if not repo: renderers = (JSONRenderer,)
return api_error(request, '404', "repo not found")
password_set = False @api_login_required
if repo.props.encrypted: def get(self, request, repo_id, dir_id):
try: if not can_access_repo(request, repo_id):
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username) return api_error(request, '403', "can not access repo")
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
if repo.props.encrypted and not password_set: repo = get_repo(repo_id)
return api_error(request, '403', "password needed") if not repo:
return api_error(request, '404', "repo not found")
return get_dir_entrys_by_id(request, dir_id) password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
@login_required if repo.props.encrypted and not password_set:
def get_repo_file_id(request, repo_id, file_id): return api_error(request, '403', "password needed")
if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
repo = get_repo(repo_id) return get_dir_entrys_by_id(request, dir_id)
if not repo:
return api_error(request, '404', "repo not found")
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
if repo.props.encrypted and not password_set: class RepoFileView(ResponseMixin, View):
return api_error(request, '403', "password needed") renderers = (JSONRenderer,)
file_name = request.GET.get('file_name', file_id)
token = gen_token()
# put token into memory in seaf-server
seafserv_rpc.web_save_access_token(token, file_id)
http_server_root = get_httpserver_root() @api_login_required
op='download' def get(self, request, repo_id, file_id):
redirect_url = '%s/access?repo_id=%s&id=%s&filename=%s&op=%s&t=%s&u=%s' % (http_server_root, if not can_access_repo(request, repo_id):
return api_error(request, '403', "can not access repo")
repo = get_repo(repo_id)
if not repo:
return api_error(request, '404', "repo not found")
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return api_error(request, '403', e.msg)
if repo.props.encrypted and not password_set:
return api_error(request, '403', "password needed")
file_name = request.GET.get('file_name', file_id)
token = gen_token()
# put token into memory in seaf-server
seafserv_rpc.web_save_access_token(token, file_id)
http_server_root = get_httpserver_root()
op='download'
redirect_url = '%s/access?repo_id=%s&id=%s&filename=%s&op=%s&t=%s&u=%s' % (http_server_root,
repo_id, file_id, repo_id, file_id,
file_name, op, file_name, op,
token, token,
request.user.username) request.user.username)
return HttpResponseRedirect(redirect_url) return HttpResponseRedirect(redirect_url)

View File

@@ -44,6 +44,44 @@ def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
return actual_decorator return actual_decorator
def api_user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
def decorator(view_func):
def _wrapped_view(obj, request, *args, **kwargs):
if test_func(request.user):
return view_func(obj, request, *args, **kwargs)
path = urlquote(request.get_full_path())
tup = login_url, redirect_field_name, path
json_content_type = 'application/json; charset=utf-8'
return HttpResponse(json.dumps('%s?%s=%s' % tup), status=401,
content_type=json_content_type)
return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
return decorator
def api_login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = api_user_passes_test(
lambda u: u.is_authenticated(),
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
def permission_required(perm, login_url=None): def permission_required(perm, login_url=None):
""" """
Decorator for views that checks whether a user has a particular permission Decorator for views that checks whether a user has a particular permission

View File

@@ -43,7 +43,6 @@ urlpatterns = patterns('',
(r'^share/', include('share.urls')), (r'^share/', include('share.urls')),
(r'^api/', include('api.urls')), (r'^api/', include('api.urls')),
(r'^rest/', include('djangorestframework.urls')),
url(r'^shareadmin/$', share_admin, name='share_admin'), url(r'^shareadmin/$', share_admin, name='share_admin'),
(r'^shareadmin/removeshare/$', repo_remove_share), (r'^shareadmin/removeshare/$', repo_remove_share),
(r'^sharedlink/get/$', get_shared_link), (r'^sharedlink/get/$', get_shared_link),