mirror of
https://github.com/haiwen/seahub.git
synced 2025-06-25 22:54:07 +00:00
715 lines
23 KiB
Python
715 lines
23 KiB
Python
|
# encoding: utf-8
|
||
|
import os
|
||
|
import stat
|
||
|
from urllib2 import unquote, quote
|
||
|
import seahub.settings as settings
|
||
|
|
||
|
from rest_framework import parsers
|
||
|
from rest_framework import status
|
||
|
from rest_framework import renderers
|
||
|
from rest_framework.permissions import IsAuthenticated
|
||
|
from rest_framework.response import Response
|
||
|
from rest_framework.views import APIView
|
||
|
from django.contrib.sites.models import RequestSite
|
||
|
|
||
|
from models import Token
|
||
|
from mime import get_file_mime
|
||
|
from authentication import TokenAuthentication
|
||
|
from serializers import AuthTokenSerializer
|
||
|
from base.accounts import User
|
||
|
from share.models import FileShare
|
||
|
from seahub.views import access_to_repo, validate_owner
|
||
|
from seahub.utils import gen_file_get_url, gen_token, gen_file_upload_url, \
|
||
|
check_filename_with_rename, get_starred_files
|
||
|
|
||
|
from pysearpc import SearpcError
|
||
|
from seaserv import seafserv_rpc, seafserv_threaded_rpc, \
|
||
|
get_personal_groups_by_user, \
|
||
|
get_group_repos, get_repo, check_permission, get_commits
|
||
|
|
||
|
class Ping(APIView):
|
||
|
"""
|
||
|
Returns a simple `pong` message when client calls `api2/ping/`.
|
||
|
For example:
|
||
|
curl http://127.0.0.1:8000/api2/ping/
|
||
|
"""
|
||
|
def get(self, request, format=None):
|
||
|
return Response('pong')
|
||
|
|
||
|
class AuthPing(APIView):
|
||
|
"""
|
||
|
Returns a simple `pong` message when client provided an auth token.
|
||
|
For example:
|
||
|
curl -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" http://127.0.0.1:8000/api2/auth/ping/
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, format=None):
|
||
|
return Response('pong')
|
||
|
|
||
|
class ObtainAuthToken(APIView):
|
||
|
"""
|
||
|
Returns auth token if username and password are valid.
|
||
|
For example:
|
||
|
curl -d "username=xiez1989@gmail.com&password=123456" http://127.0.0.1:8000/api2/auth-token/
|
||
|
"""
|
||
|
throttle_classes = ()
|
||
|
permission_classes = ()
|
||
|
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||
|
renderer_classes = (renderers.JSONRenderer,)
|
||
|
model = Token
|
||
|
|
||
|
def post(self, request):
|
||
|
serializer = AuthTokenSerializer(data=request.DATA)
|
||
|
if serializer.is_valid():
|
||
|
token, created = Token.objects.get_or_create(user=serializer.object['user'].username)
|
||
|
return Response({'token': token.key})
|
||
|
|
||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||
|
|
||
|
HTTP_ERRORS = {
|
||
|
'400':'Bad arguments',
|
||
|
'401':'Login required',
|
||
|
'402':'Incorrect repo password',
|
||
|
'403':'Can not access repo',
|
||
|
'404':'Repo not found',
|
||
|
'405':'Query password set error',
|
||
|
'406':'Repo is not encrypted',
|
||
|
'407':'Method not supported',
|
||
|
'408':'Login failed',
|
||
|
'409':'Repo password required',
|
||
|
'410':'Path does not exist',
|
||
|
'411':'Failed to get dirid by path',
|
||
|
'412':'Failed to get fileid by path',
|
||
|
'413':'Above quota',
|
||
|
'415':'Operation not supported',
|
||
|
'416':'Failed to list dir',
|
||
|
'417':'Set password error',
|
||
|
'418':'Failed to delete',
|
||
|
'419':'Failed to move',
|
||
|
'420':'Failed to rename',
|
||
|
'421':'Failed to mkdir',
|
||
|
|
||
|
'499':'Unknow Error',
|
||
|
|
||
|
'500':'Internal server error',
|
||
|
'501':'Failed to get shared link',
|
||
|
'502':'Failed to send shared link',
|
||
|
}
|
||
|
|
||
|
def api_error(code='499', msg=None):
|
||
|
err_resp = {'error_msg': msg if msg else HTTP_ERRORS[code]}
|
||
|
return Response(err_resp, status=code)
|
||
|
|
||
|
class Account(APIView):
|
||
|
"""
|
||
|
Show account info.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, format=None):
|
||
|
info = {}
|
||
|
email = request.user.username
|
||
|
info['email'] = email
|
||
|
info['usage'] = seafserv_threaded_rpc.get_user_quota_usage(email)
|
||
|
info['total'] = seafserv_threaded_rpc.get_user_quota(email)
|
||
|
info['feedback'] = settings.DEFAULT_FROM_EMAIL
|
||
|
return Response(info)
|
||
|
|
||
|
def calculate_repo_info(repo_list, username):
|
||
|
"""
|
||
|
Get some info for repo.
|
||
|
|
||
|
"""
|
||
|
for repo in repo_list:
|
||
|
try:
|
||
|
commit = get_commits(repo.id, 0, 1)[0]
|
||
|
repo.latest_modify = commit.ctime
|
||
|
repo.root = commit.root_id
|
||
|
repo.size = seafserv_threaded_rpc.server_repo_size(repo.id)
|
||
|
if not repo.size :
|
||
|
repo.size = 0;
|
||
|
|
||
|
password_need = False
|
||
|
if repo.encrypted:
|
||
|
try:
|
||
|
ret = seafserv_rpc.is_passwd_set(repo.id, username)
|
||
|
if ret != 1:
|
||
|
password_need = True
|
||
|
except SearpcErroe, e:
|
||
|
pass
|
||
|
repo.password_need = password_need
|
||
|
except Exception,e:
|
||
|
repo.latest_modify = 0
|
||
|
repo.commit = None
|
||
|
repo.size = -1
|
||
|
repo.password_need = None
|
||
|
|
||
|
class Repos(APIView):
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, format=None):
|
||
|
email = request.user.username
|
||
|
|
||
|
owned_repos = seafserv_threaded_rpc.list_owned_repos(email)
|
||
|
calculate_repo_info (owned_repos, email)
|
||
|
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
|
||
|
|
||
|
n_repos = seafserv_threaded_rpc.list_share_repos(email,
|
||
|
'to_email', -1, -1)
|
||
|
calculate_repo_info (n_repos, email)
|
||
|
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
|
||
|
|
||
|
repos_json = []
|
||
|
for r in owned_repos:
|
||
|
repo = {
|
||
|
"type":"repo",
|
||
|
"id":r.id,
|
||
|
"owner":email,
|
||
|
"name":r.name,
|
||
|
"desc":r.desc,
|
||
|
"mtime":r.latest_modify,
|
||
|
"root":r.root,
|
||
|
"size":r.size,
|
||
|
"encrypted":r.encrypted,
|
||
|
"password_need":r.password_need,
|
||
|
}
|
||
|
repos_json.append(repo)
|
||
|
|
||
|
for r in n_repos:
|
||
|
repo = {
|
||
|
"type":"srepo",
|
||
|
"id":r.id,
|
||
|
"owner":r.shared_email,
|
||
|
"name":r.name,
|
||
|
"desc":r.desc,
|
||
|
"mtime":r.latest_modify,
|
||
|
"root":r.root,
|
||
|
"size":r.size,
|
||
|
"encrypted":r.encrypted,
|
||
|
"password_need":r.password_need,
|
||
|
}
|
||
|
repos_json.append(repo)
|
||
|
|
||
|
groups = get_personal_groups_by_user(email)
|
||
|
for group in groups:
|
||
|
g_repos = get_group_repos(group.id, email)
|
||
|
calculate_repo_info (g_repos, email)
|
||
|
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
|
||
|
for r in g_repos:
|
||
|
repo = {
|
||
|
"type":"grepo",
|
||
|
"id":r.id,
|
||
|
"owner":group.group_name,
|
||
|
"name":r.name,
|
||
|
"desc":r.desc,
|
||
|
"mtime":r.latest_modify,
|
||
|
"root":r.root,
|
||
|
"size":r.size,
|
||
|
"encrypted":r.encrypted,
|
||
|
"password_need":r.password_need,
|
||
|
}
|
||
|
repos_json.append(repo)
|
||
|
|
||
|
return Response(repos_json)
|
||
|
|
||
|
def can_access_repo(request, repo_id):
|
||
|
if not check_permission(repo_id, request.user.username):
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
class Repo(APIView):
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id, format=None):
|
||
|
# check whether user can view repo
|
||
|
repo = get_repo(repo_id)
|
||
|
if not repo:
|
||
|
return api_error('404')
|
||
|
|
||
|
if not can_access_repo(request, repo.id):
|
||
|
return api_error('403')
|
||
|
|
||
|
# check whether use is repo owner
|
||
|
if validate_owner(request, repo_id):
|
||
|
owner = "self"
|
||
|
else:
|
||
|
owner = "share"
|
||
|
|
||
|
try:
|
||
|
repo.latest_modify = get_commits(repo.id, 0, 1)[0].ctime
|
||
|
except:
|
||
|
repo.latest_modify = None
|
||
|
|
||
|
# query repo infomation
|
||
|
repo.size = seafserv_threaded_rpc.server_repo_size(repo_id)
|
||
|
current_commit = get_commits(repo_id, 0, 1)[0]
|
||
|
repo_json = {
|
||
|
"type":"repo",
|
||
|
"id":repo.id,
|
||
|
"owner":owner,
|
||
|
"name":repo.name,
|
||
|
"desc":repo.desc,
|
||
|
"mtime":repo.lastest_modify,
|
||
|
"size":repo.size,
|
||
|
"encrypted":repo.encrypted,
|
||
|
"root":current_commit.root_id,
|
||
|
"password_need":repo.password_need,
|
||
|
}
|
||
|
|
||
|
return Response(repo_json)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
resp = check_repo_access_permission(request, get_repo(repo_id))
|
||
|
if resp:
|
||
|
return resp
|
||
|
op = request.GET.get('op', 'setpassword')
|
||
|
if op == 'setpassword':
|
||
|
return Response("success")
|
||
|
|
||
|
return Response("unsupported operation")
|
||
|
|
||
|
def check_repo_access_permission(request, repo):
|
||
|
if not repo:
|
||
|
return api_error('404')
|
||
|
|
||
|
if not can_access_repo(request, repo.id):
|
||
|
return api_error('403')
|
||
|
|
||
|
password_set = False
|
||
|
if repo.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('405', "SearpcError:" + e.msg)
|
||
|
|
||
|
if not password_set:
|
||
|
password = request.REQUEST.get('password', default=None)
|
||
|
if not password:
|
||
|
return api_error('409')
|
||
|
|
||
|
return set_repo_password(request, repo, password)
|
||
|
|
||
|
def get_file_size (id):
|
||
|
size = seafserv_threaded_rpc.get_file_size(id)
|
||
|
return size if size else 0
|
||
|
|
||
|
def get_dir_entrys_by_id(request, dir_id):
|
||
|
dentrys = []
|
||
|
try:
|
||
|
dirs = seafserv_threaded_rpc.list_dir(dir_id)
|
||
|
except SearpcError, e:
|
||
|
return api_error("416")
|
||
|
|
||
|
for dirent in dirs:
|
||
|
dtype = "file"
|
||
|
entry={}
|
||
|
if stat.S_ISDIR(dirent.mode):
|
||
|
dtype = "dir"
|
||
|
else:
|
||
|
mime = get_file_mime(dirent.obj_name)
|
||
|
if mime:
|
||
|
entry["mime"] = mime
|
||
|
try:
|
||
|
entry["size"] = get_file_size(dirent.obj_id)
|
||
|
except Exception, e:
|
||
|
entry["size"]=0
|
||
|
|
||
|
entry["type"]=dtype
|
||
|
entry["name"]=dirent.obj_name
|
||
|
entry["id"]=dirent.obj_id
|
||
|
dentrys.append(entry)
|
||
|
return Response(dentrys)
|
||
|
# response = HttpResponse(json.dumps(dentrys), status=200,
|
||
|
# content_type=json_content_type)
|
||
|
# response["oid"] = dir_id
|
||
|
# return response
|
||
|
|
||
|
class RepoDirents(APIView):
|
||
|
"""
|
||
|
List directory entries of a repo.
|
||
|
TODO: may be better use dirent id instead of path.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id):
|
||
|
repo = get_repo(repo_id)
|
||
|
resp = check_repo_access_permission(request, repo)
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
current_commit = get_commits(repo_id, 0, 1)[0]
|
||
|
path = request.GET.get('p', '/')
|
||
|
if path[-1] != '/':
|
||
|
path = path + '/'
|
||
|
|
||
|
dir_id = None
|
||
|
try:
|
||
|
dir_id = seafserv_threaded_rpc.get_dirid_by_path(current_commit.id,
|
||
|
path.encode('utf-8'))
|
||
|
except SearpcError, e:
|
||
|
return api_error("411", "SearpcError:" + e.msg)
|
||
|
|
||
|
if not dir_id:
|
||
|
return api_error('410')
|
||
|
|
||
|
old_oid = request.GET.get('oid', None)
|
||
|
if old_oid and old_oid == dir_id :
|
||
|
response = HttpResponse(json.dumps("uptodate"), status=200,
|
||
|
content_type=json_content_type)
|
||
|
response["oid"] = dir_id
|
||
|
return response
|
||
|
else:
|
||
|
return get_dir_entrys_by_id(request, dir_id)
|
||
|
|
||
|
class RepoDirs(APIView):
|
||
|
"""
|
||
|
List directory entries based on dir_id.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id, dir_id, format=None):
|
||
|
repo = get_repo(repo_id)
|
||
|
resp = check_repo_access_permission(request, repo)
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
return get_dir_entrys_by_id(request, dir_id)
|
||
|
|
||
|
def get_shared_link(request, repo_id, path):
|
||
|
l = FileShare.objects.filter(repo_id=repo_id).filter(\
|
||
|
username=request.user.username).filter(path=path)
|
||
|
token = None
|
||
|
if len(l) > 0:
|
||
|
fileshare = l[0]
|
||
|
token = fileshare.token
|
||
|
else:
|
||
|
token = gen_token(max_length=10)
|
||
|
|
||
|
fs = FileShare()
|
||
|
fs.username = request.user.username
|
||
|
fs.repo_id = repo_id
|
||
|
fs.path = path
|
||
|
fs.token = token
|
||
|
|
||
|
try:
|
||
|
fs.save()
|
||
|
except IntegrityError, e:
|
||
|
return api_err('501')
|
||
|
|
||
|
domain = RequestSite(request).domain
|
||
|
file_shared_link = 'http://%s%sf/%s/' % (domain,
|
||
|
settings.SITE_ROOT, token)
|
||
|
return Response(file_shared_link)
|
||
|
|
||
|
def get_repo_file(request, repo_id, file_id, file_name, op):
|
||
|
if op == 'download':
|
||
|
token = seafserv_rpc.web_get_access_token(repo_id, file_id,
|
||
|
op, request.user.username)
|
||
|
redirect_url = gen_file_get_url(token, file_name)
|
||
|
return Response(redirect_url)
|
||
|
# response = HttpResponse(json.dumps(redirect_url), status=200,
|
||
|
# content_type=json_content_type)
|
||
|
# response["oid"] = file_id
|
||
|
# return response
|
||
|
|
||
|
if op == 'sharelink':
|
||
|
path = request.GET.get('p', None)
|
||
|
assert path, 'path must be passed in the url'
|
||
|
return get_shared_link(request, repo_id, path)
|
||
|
|
||
|
class RepoFilepath(APIView):
|
||
|
"""
|
||
|
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id, format=None):
|
||
|
repo = get_repo(repo_id)
|
||
|
resp = check_repo_access_permission(request, repo)
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
path = request.GET.get('p', None)
|
||
|
if not path:
|
||
|
return api_error('413')
|
||
|
|
||
|
file_id = None
|
||
|
try:
|
||
|
file_id = seafserv_threaded_rpc.get_file_by_path(repo_id,
|
||
|
path.encode('utf-8'))
|
||
|
except SearpcError, e:
|
||
|
return api_error('412', "SearpcError:" + e.msg)
|
||
|
|
||
|
if not file_id:
|
||
|
return api_error('410')
|
||
|
|
||
|
file_name = request.GET.get('file_name', file_id)
|
||
|
op = request.GET.get('op', 'download')
|
||
|
return get_repo_file(request, repo_id, file_id, file_name, op)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
repo = get_repo(repo_id)
|
||
|
resp = check_repo_access_permission(request, repo)
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
path = request.GET.get('p', None)
|
||
|
if not path:
|
||
|
return api_error('413', 'Path needed')
|
||
|
|
||
|
op = request.GET.get('op', 'sendsharelink')
|
||
|
if op == 'sendsharelink':
|
||
|
emails = request.POST.get('email', None)
|
||
|
if not emails:
|
||
|
return api_error('400', "Email required")
|
||
|
return send_share_link(request, path, emails)
|
||
|
elif op == 'star':
|
||
|
org_id = int(request.GET.get('org', '-1'))
|
||
|
star_file(request.user.username, repo_id, path, False, org_id=org_id)
|
||
|
return HttpResponse('success')
|
||
|
elif op == 'unstar':
|
||
|
unstar_file(request.user.username, repo_id, path)
|
||
|
return HttpResponse('success')
|
||
|
return api_error('415')
|
||
|
|
||
|
class RepoFiles(APIView):
|
||
|
"""
|
||
|
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id, file_id, format=None):
|
||
|
repo = get_repo(repo_id)
|
||
|
resp = check_repo_access_permission(request, repo)
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
file_name = request.GET.get('file_name', file_id)
|
||
|
return get_repo_file(request, repo_id, file_id, file_name, 'download')
|
||
|
|
||
|
def reloaddir_if_neccessary (request, repo_id, parent_dir):
|
||
|
reloaddir = False
|
||
|
s = request.GET.get('reloaddir', None)
|
||
|
if s and s.lower() == 'true':
|
||
|
reloaddir = True
|
||
|
|
||
|
if not reloaddir:
|
||
|
return Response('success')
|
||
|
|
||
|
current_commit = get_commits(repo_id, 0, 1)[0]
|
||
|
try:
|
||
|
dir_id = seafserv_threaded_rpc.get_dirid_by_path(current_commit.id,
|
||
|
parent_dir.encode('utf-8'))
|
||
|
except SearpcError, e:
|
||
|
return api_error("411", "SearpcError:" + e.msg)
|
||
|
|
||
|
if not dir_id:
|
||
|
return api_error('410')
|
||
|
return get_dir_entrys_by_id(request, dir_id)
|
||
|
|
||
|
class OpDeleteView(APIView):
|
||
|
"""
|
||
|
Delete a file.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
resp = check_repo_access_permission(request, get_repo(repo_id))
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
parent_dir = request.GET.get('p', '/')
|
||
|
file_names = request.POST.get("file_names")
|
||
|
|
||
|
if not parent_dir or not file_names:
|
||
|
return api_error('400')
|
||
|
|
||
|
names = file_names.split(':')
|
||
|
names = map(lambda x: unquote(x).decode('utf-8'), names)
|
||
|
|
||
|
for file_name in names:
|
||
|
try:
|
||
|
seafserv_threaded_rpc.del_file(repo_id, parent_dir,
|
||
|
file_name, request.user.username)
|
||
|
except SearpcError,e:
|
||
|
return api_error('418', 'SearpcError:' + e.msg)
|
||
|
|
||
|
return reloaddir_if_neccessary (request, repo_id, parent_dir)
|
||
|
|
||
|
class OpRenameView(APIView):
|
||
|
"""
|
||
|
Rename a file.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
resp = check_repo_access_permission(request, get_repo(repo_id))
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
path = request.GET.get('p')
|
||
|
newname = request.POST.get("newname")
|
||
|
if not path or path[0] != '/' or not newname:
|
||
|
return api_error('400')
|
||
|
|
||
|
newname = unquote(newname).decode('utf-8')
|
||
|
if len(newname) > settings.MAX_UPLOAD_FILE_NAME_LEN:
|
||
|
return api_error('420', 'New name too long')
|
||
|
|
||
|
parent_dir = os.path.dirname(path)
|
||
|
oldname = os.path.basename(path)
|
||
|
|
||
|
if oldname == newname:
|
||
|
return api_error('420', 'The new name is the same to the old')
|
||
|
|
||
|
newname = check_filename_with_rename(repo_id, parent_dir, newname)
|
||
|
|
||
|
try:
|
||
|
seafserv_threaded_rpc.rename_file (repo_id, parent_dir, oldname,
|
||
|
newname, request.user.username)
|
||
|
except SearpcError,e:
|
||
|
return api_error('420', "SearpcError:" + e.msg)
|
||
|
|
||
|
return reloaddir_if_neccessary (request, repo_id, parent_dir)
|
||
|
|
||
|
class OpMoveView(APIView):
|
||
|
"""
|
||
|
Move a file.
|
||
|
TODO: should be refactored and splited.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
src_repo_id = request.POST.get('src_repo')
|
||
|
src_dir = unquote(request.POST.get('src_dir')).decode('utf-8')
|
||
|
dst_repo_id = request.POST.get('dst_repo')
|
||
|
dst_dir = unquote(request.POST.get('dst_dir')).decode('utf-8')
|
||
|
op = request.POST.get('operation')
|
||
|
obj_names = request.POST.get('obj_names')
|
||
|
print src_repo_id, dst_repo_id, src_dir, dst_dir, op, obj_names
|
||
|
if not (src_repo_id and src_dir and dst_repo_id \
|
||
|
and dst_dir and op and obj_names):
|
||
|
return api_error('400')
|
||
|
|
||
|
if src_repo_id == dst_repo_id and src_dir == dst_dir:
|
||
|
return api_error('419', 'The src_dir is same to dst_dir')
|
||
|
|
||
|
names = obj_names.split(':')
|
||
|
names = map(lambda x: unquote(x).decode('utf-8'), names)
|
||
|
|
||
|
if dst_dir.startswith(src_dir):
|
||
|
for obj_name in names:
|
||
|
if dst_dir.startswith('/'.join([src_dir, obj_name])):
|
||
|
return api_error('419', 'Can not move a dirctory to its subdir')
|
||
|
|
||
|
for obj_name in names:
|
||
|
new_obj_name = check_filename_with_rename(dst_repo_id, dst_dir, obj_name)
|
||
|
|
||
|
try:
|
||
|
if op == 'cp':
|
||
|
seafserv_threaded_rpc.copy_file (src_repo_id, src_dir, obj_name,
|
||
|
dst_repo_id, dst_dir, new_obj_name,
|
||
|
request.user.username)
|
||
|
elif op == 'mv':
|
||
|
seafserv_threaded_rpc.move_file (src_repo_id, src_dir, obj_name,
|
||
|
dst_repo_id, dst_dir, new_obj_name,
|
||
|
request.user.username)
|
||
|
except SearpcError, e:
|
||
|
return api_error('419', "SearpcError:" + e.msg)
|
||
|
|
||
|
return reloaddir_if_neccessary (request, dst_repo_id, dst_dir)
|
||
|
|
||
|
class OpMkdirView(APIView):
|
||
|
"""
|
||
|
Make a new directory.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def post(self, request, repo_id, format=None):
|
||
|
resp = check_repo_access_permission(request, get_repo(repo_id))
|
||
|
if resp:
|
||
|
return resp
|
||
|
|
||
|
path = request.GET.get('p')
|
||
|
if not path or path[0] != '/':
|
||
|
return api_error('400')
|
||
|
|
||
|
parent_dir = os.path.dirname(path)
|
||
|
new_dir_name = os.path.basename(path)
|
||
|
new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name)
|
||
|
|
||
|
try:
|
||
|
seafserv_threaded_rpc.post_dir(repo_id, parent_dir, new_dir_name,
|
||
|
request.user.username)
|
||
|
except SearpcError, e:
|
||
|
return api_error('421', e.msg)
|
||
|
|
||
|
return reloaddir_if_neccessary (request, repo_id, parent_dir)
|
||
|
|
||
|
class OpUploadView(APIView):
|
||
|
"""
|
||
|
Upload a file.
|
||
|
"""
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, repo_id, format=None):
|
||
|
repo = get_repo(repo_id)
|
||
|
if check_permission(repo_id, request.user.username) == 'rw':
|
||
|
token = seafserv_rpc.web_get_access_token(repo_id,
|
||
|
'dummy',
|
||
|
'upload',
|
||
|
request.user.username)
|
||
|
else:
|
||
|
return api_error('403')
|
||
|
|
||
|
if request.cloud_mode and seafserv_threaded_rpc.check_quota(repo_id) < 0:
|
||
|
return api_error('413')
|
||
|
|
||
|
upload_url = gen_file_upload_url(token, 'upload')
|
||
|
return Response(upload_url)
|
||
|
|
||
|
def append_starred_files(array, files):
|
||
|
for f in files:
|
||
|
sfile = {'org' : f.org_id,
|
||
|
'repo' : f.repo.id,
|
||
|
'path' : f.path,
|
||
|
'mtime' : f.last_modified,
|
||
|
'dir' : f.is_dir,
|
||
|
'size' : f.size
|
||
|
}
|
||
|
array.append(sfile)
|
||
|
|
||
|
def api_starred_files(request):
|
||
|
starred_files = []
|
||
|
personal_files = get_starred_files(request.user.username, -1)
|
||
|
append_starred_files (starred_files, personal_files)
|
||
|
return Response(starred_files)
|
||
|
|
||
|
class StarredFileView(APIView):
|
||
|
"""
|
||
|
Get starred files list.
|
||
|
"""
|
||
|
|
||
|
authentication_classes = (TokenAuthentication, )
|
||
|
permission_classes = (IsAuthenticated,)
|
||
|
|
||
|
def get(self, request, format=None):
|
||
|
return api_starred_files(request)
|
||
|
|